mysql2详解

作者:周星 发布:2017-10-07

       当前进行的项目中有这样一个需求,它要求我们从远程的 mysql 数据库中导入数据到本地,并和 Rails的 model 对应起来,ruby 有很多操作 mysql 的模块或 gem,这其中 [mysql2](https://github.com/brianmario/mysql2) 是一个最常用的一个,它可以让我们优雅、高效的操作 mysql 数据库,Rails 项目默认使用了此 gem。下面我们来看一下如何使用它:
       mysql2 的 API 由两个类组成,我们会经常使用到它们:

Mysql2::Client - 与数据库的链接
Mysql2::Result - 执行的结果,它 mixin 了Enumerable 模块

       安装方式同大多数 gem 一样:

gem install mysql2
# 或者在 gemfile 里添加
gem mysql2

       使用 gem install mysql2 安装时你可以指定如下参数:--with-mysql-dir[=/path/to/mysqldir] 、 --with-mysql-config[=/path/to/mysql_config] 、--with-mysql-rpath=/path/to/mysql/lib / --without-mysql-rpath,它们与 MySQL 的安装目录、mysql_config、运行路径有关,一般你很难接触到它们,本次分享不会介绍关于这几个参数更多的信息。

使用:

client = Mysql2::Client.new(:host => "localhost", :username => "root")
results = client.query("SELECT * FROM users WHERE id < 1000")

       如果你尝试上面的两行却报错,那无关紧要,请你继续往下看,聪明的你一定从上面的看出了代码所做的工作,首先通过指定的 host 和 username 建立了一个 MySQL 链接,然后执行了一个查询,找到所有 id < 1000 的用户,并返回一个 Mysql::Result 类型的对象给我们,上面我们说到,Mysql::Result mixin 了 Enumerable 模块,所以你可以在 results 上使用所有 Enumerable 模块定义的方法:

results.first              # 第一条数据
results.count              # 结果总数
# 遍历 results
results.each do |row|
  puts row["id"]
end

       each 块内的临时变量 row 为一个 hash,hash 的键为对应数据表的 field,这让我们非常方便的获取数据,如果你想以 ruby symbol 的方式取数据,你可以使用参数:

client.query("SELECT * FROM users WHERE id < 1000", :symbolize_keys => true) do |row|
  puts row[:id]
end

想获取所有的 columns?

results.fields

       上面说到执行 client = Mysql2::Client.new(:host => "localhost", :username => "root") 时可能会报错,因为 Mysql 会向你索要密码,Mysql2::Client 的初始化支持很多参数,你可以按需指定:

Mysql2::Client.new(
  :host,
  :username,
  :password,
  :port,
  :database,
  :socket = '/path/to/mysql.sock',
  :flags = REMEMBER_OPTIONS | LONG_PASSWORD | LONG_FLAG | TRANSACTIONS | PROTOCOL_41 | SECURE_CONNECTION | MULTI_STATEMENTS,
  :encoding = 'utf8',
  :read_timeout = seconds,
  :write_timeout = seconds,
  :connect_timeout = seconds,
  :reconnect = true/false,
  :local_infile = true/false,
  :secure_auth = true/false,
  :default_file = '/path/to/my.cfg',
  :default_group = 'my.cfg section',
  :init_command => sql
)

所以一般来说,你需要指定链接 Mysql 的密码和数据库

client = Mysql2::Client.new(:host => "localhost", :username => "root", :password => "root", database: "mywebsite")

       看到上面的初始化参数,你有没有想到什么?对了!就是我们 Rails 项目的 database.yml!

development:
  adapter: mysql2
  encoding: utf8
  database: my_db_name
  username: root
  password: my_password
  host: 127.0.0.1
  port: 3306
  secure_auth: false

       从 MySQL5.6.5 开始,secure_auth 是默认开启的,我们不会介绍关于 secure_auth 的内容,不过你可以通过参数 secure_auth: false 关闭它。如果你想了解更多有关 secure_auth 内容,请 [参考这里](http://dev.mysql.com/doc/refman/5.6/en/mysql-command-options.html#option_mysql_secure-auth)。
       上面所述的内容为常见内容,可以满足一般的使用了,下面是一些扩展,当然有些时候你可能也会使用到它们。

SSL 选项:

       设置下面的任何参数都会开启 SSL 链接,我们不会介绍有关 SSL 的内容,你可以 [参考这里](http://en.wikipedia.org/wiki/SSL),一般来说你的 MySQL 不会开启SSL,除非你是使用 SSL 相关编译的。

Mysql2::Client.new(
  # ..下面的参数...,
  :sslkey => '/path/to/client-key.pem',
  :sslcert => '/path/to/client-cert.pem',
  :sslca => '/path/to/ca-cert.pem',
  :sslcapath => '/path/to/cacerts',
  :sslcipher => 'DHE-RSA-AES256-SHA'
  )

       可以通过传递参数 :default_file 和 :default_group 来读取 MySQL 的配置选项:

Mysql2::Client.new(:default_file => '/user/.my.cnf', :default_group => 'client')

       mysql2 可以异步的执行查询,这意味着如果一个查询时间较长,它不会阻塞后面的请求,这是我非常欣赏的地方,通过指定参数 :async => true 和 ruby 代码,你可以将其做到完美:

client.query("SELECT sleep(5)", :async => true)

       注意:此行代码执行结果会立即返回给我们 nil,所以你可能需要使用一些 socket 监管工具,一旦 socket 可读,你就马上去获取结果:

result = client.async_result

       默认情况下 mysql2 缓存了 rows ,这是非常实用的,尤其是当你需要反复使用它,但是如果你只想遍历一次就丢掉,请通过 :cache_rows 关掉它。

       关于获取大量数据:

       如果你想获取大量数据,我有两个建议:分批查询或者指定 :stream => true,分批查询哲学类似分页,在各种场合均常见,而 :stream => true 则是 mysql2 给我们的特殊用法:

result = client.query("SELECT * FROM really_big_Table", :stream => true)

但是需要注意:

 :cache_rows 将不能使用你必须获取所有的 rows ,否则将不能做新的查询

博主并未亲测 mysql2 与其它 gem 的性能差异,官网上有详细的数据可供参考。

如果您想了解更多关于 mysql2 的内容,请阅读 mysql2 的源码,并与博主探讨。

mysql2项目地址

如果您对本文有什么意见或建议,请联系博主。

支付宝扫码赞助博主


评论(0)