Ruby 连接 Mysql – MySql2

在 Ruby 中,Mysql2 是一个高效、现代的 Ruby 库,用于连接和操作 MySQL 数据库。相比 DBI,Mysql2 更轻量、性能更高,且与 Rails 等框架集成良好。以下是对 Ruby 使用 Mysql2 连接 MySQL 数据库的中文讲解,涵盖安装、连接、基本操作(增删改查)、事务处理及注意事项,力求简洁清晰。


1. Mysql2 简介

Mysql2 是一个 Ruby 的 MySQL 客户端库,直接与 MySQL C API 交互,提供快速、可靠的数据库访问。它是 Rails 默认的 MySQL 适配器,广泛用于 Web 开发。

优点

  • 高性能:基于 libmysqlclient,速度快。
  • 支持现代 MySQL 特性:如异步查询、流式结果。
  • 易于集成:与 ActiveRecord 等框架无缝配合。

2. 安装 Mysql2

先决条件

  • 安装 MySQL 服务器并运行。
  • 安装 MySQL 开发库(用于编译 Mysql2):
  • Ubuntu
    bash sudo apt-get install mysql-client libmysqlclient-dev
  • CentOS
    bash yum install mysql-devel
  • macOS
    bash brew install mysql

安装 Mysql2 gem

使用 RubyGems 安装:

gem install mysql2

验证安装

require 'mysql2'
puts Mysql2::VERSION  # 输出:0.5.4(示例版本)

说明:确保 Ruby 和 MySQL 版本兼容,安装前检查 libmysqlclient 路径。


3. 连接 MySQL 数据库

使用 Mysql2::Client.new 创建连接。

基本语法

require 'mysql2'

client = Mysql2::Client.new(
  host: "localhost",
  username: "testuser",
  password: "test123",
  database: "TESTDB"
)

示例:连接并测试

假设数据库 TESTDB 已存在,用户为 testuser,密码为 test123

require 'mysql2'

begin
  client = Mysql2::Client.new(
    host: "localhost",
    username: "testuser",
    password: "test123",
    database: "TESTDB"
  )
  result = client.query("SELECT VERSION()")
  puts "MySQL 版本: #{result.first['VERSION()']}"
rescue Mysql2::Error => e
  puts "错误: #{e.message}"
ensure
  client.close if client
end

输出(示例):

MySQL 版本: 8.0.27

说明

  • 连接参数:host, username, password, database 是必需的。
  • 可选参数:port(默认 3306)、encoding(默认 UTF-8)、ssl 等。
  • 使用 rescue 捕获 Mysql2::Errorensure 确保连接关闭。

4. 基本操作(CRUD)

假设 EMPLOYEE 表结构:FIRST_NAME, LAST_NAME, AGE, SEX, INCOME

插入(Create)

client.query("INSERT INTO EMPLOYEE (FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES ('Alice', 'Smith', 30, 'F', 3000)")
puts "记录已插入,影响行数: #{client.affected_rows}"

参数绑定(防止 SQL 注入)

client.prepare("INSERT INTO EMPLOYEE (FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES (?, ?, ?, ?, ?)")
       .execute('Bob', 'Jones', 25, 'M', 2500)
puts "记录已插入"

查询(Read)

  • 查询单行
  result = client.query("SELECT * FROM EMPLOYEE WHERE FIRST_NAME = 'Alice'")
  result.each do |row|
    puts "姓名: #{row['FIRST_NAME']} #{row['LAST_NAME']}, 收入: #{row['INCOME']}"
  end

输出(示例):

  姓名: Alice Smith, 收入: 3000
  • 查询多行(流式处理)
  result = client.query("SELECT * FROM EMPLOYEE WHERE INCOME > 2000", stream: true)
  result.each do |row|
    puts "姓名: #{row['FIRST_NAME']} #{row['LAST_NAME']}, 收入: #{row['INCOME']}"
  end

说明stream: true 适合处理大结果集,减少内存占用。

更新(Update)

client.query("UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = 'M'")
puts "记录已更新,影响行数: #{client.affected_rows}"

删除(Delete)

client.query("DELETE FROM EMPLOYEE WHERE AGE > 30")
puts "记录已删除,影响行数: #{client.affected_rows}"

5. 事务处理

Mysql2 支持事务操作,确保数据一致性。

client.query("START TRANSACTION")
begin
  client.query("INSERT INTO EMPLOYEE (FIRST_NAME, LAST_NAME, AGE, SEX, INCOME) VALUES ('Zara', 'Ali', 20, 'F', 1500)")
  client.query("UPDATE EMPLOYEE SET INCOME = INCOME + 100 WHERE FIRST_NAME = 'Zara'")
  client.query("COMMIT")
rescue Mysql2::Error => e
  puts "错误: #{e.message}"
  client.query("ROLLBACK")
end

说明

  • 使用 START TRANSACTION, COMMIT, ROLLBACK 手动管理事务。
  • Mysql2 没有内置 transaction 块,需手动处理。

6. 错误处理

捕获 Mysql2::Error 处理数据库错误:

begin
  client = Mysql2::Client.new(
    host: "localhost",
    username: "testuser",
    password: "wrongpass",
    database: "TESTDB"
  )
rescue Mysql2::Error => e
  puts "错误: #{e.message} (代码: #{e.errno})"
end

输出(示例):

错误: Access denied for user 'testuser'@'localhost' (using password: YES) (代码: 1045)

7. 高级功能

  • 异步查询
  client.query("SELECT * FROM EMPLOYEE", async: true)
  # 异步处理其他任务
  result = client.async_result
  result.each { |row| puts row['FIRST_NAME'] }
  • 结果处理选项
  • as: :hash(默认,返回哈希)。
  • as: :array(返回数组)。
  result = client.query("SELECT FIRST_NAME, AGE FROM EMPLOYEE", as: :array)
  result.each { |row| puts "姓名: #{row[0]}, 年龄: #{row[1]}" }
  • 连接池(Rails 中常见):
  client = Mysql2::Client.new(
    host: "localhost",
    username: "testuser",
    password: "test123",
    database: "TESTDB",
    pool: 5  # 最大连接数
  )

8. 注意事项

  • 资源管理:始终关闭连接(client.close),或使用连接池管理。
  • SQL 注入:使用 prepareexecute 参数绑定,防止注入。
  # 不安全
  client.query("SELECT * FROM EMPLOYEE WHERE FIRST_NAME = '#{name}'")
  # 安全
  stmt = client.prepare("SELECT * FROM EMPLOYEE WHERE FIRST_NAME = ?")
  stmt.execute(name)
  • 编码:确保数据库和 Ruby 编码一致(如 UTF-8)。
  client = Mysql2::Client.new(..., encoding: 'utf8mb4')
  • 性能:大结果集使用 stream: true 或分页查询。
  • 现代替代:Rails 项目中,Mysql2 通常与 ActiveRecord 结合,简化操作。
  • 错误调试:检查 e.errnoe.message 获取详细错误信息。

9. 综合示例

require 'mysql2'

module EmployeeManager
  def self.list_high_earners(host, user, pass, db, min_income)
    client = Mysql2::Client.new(
      host: host,
      username: user,
      password: pass,
      database: db
    )
    stmt = client.prepare("SELECT FIRST_NAME, LAST_NAME, INCOME FROM EMPLOYEE WHERE INCOME > ?")
    result = stmt.execute(min_income)
    result.map { |row| "#{row['FIRST_NAME']} #{row['LAST_NAME']}: #{row['INCOME']}" }
  rescue Mysql2::Error => e
    ["错误: #{e.message}"]
  ensure
    client.close if client
  end
end

puts EmployeeManager.list_high_earners("localhost", "testuser", "test123", "TESTDB", 2000)
# 输出(示例):
# Alice Smith: 3000
# Bob Jones: 2500

10. 总结

Mysql2 是 Ruby 中连接 MySQL 数据库的高效工具,通过 Mysql2::Client 提供快速连接和操作。支持 CRUD、事务、异步查询和流式处理,结合参数绑定确保安全性。相比 DBI,Mysql2 更现代、性能更高,尤其适合 Rails 应用。注意资源管理、编码一致性和 SQL 注入防护,以确保代码健壮。

如果你需要更深入的示例(如复杂查询、连接池配置)或有其他问题,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注