首页 > 解决方案 > Rails ActiveRecord mysql2 适配器,默认使用 PreparedStatement

问题描述

0.4.0 版中已经添加了对 mysql2 的 PreparedStatement 支持,根据此链接
根据 0.5.2 版中的以下详细信息,它仍然没有在内部的所有 ORM 查询中使用准备好的语句:

Shipment.where(order_id: 78987898789)<br>
Shipment.where('order_id = ?', 56789876)

mysql日志:

2019-03-10T13:20:01.722848Z  1072 Query SELECT `shipments`.* FROM `shipments` WHERE `shipments`.`order_id` = 78987898789<br>
2019-03-10T13:22:27.748687Z  1072 Query SELECT `shipments`.* FROM `shipments` WHERE (order_id = 56789876)

有没有办法为所有 ORM 查询启用/禁用它?(就像 PostgreSQL 适配器ref一样)。启用它是否会对整体应用程序性能产生不利影响?

如果没有,我还没有尝试过,但是否可以使用Sequel来实现这一点,以及将现有应用程序从 MySQL2 迁移到 Sequel 有多复杂。

标签: ruby-on-railsrubyactiverecordsequelmysql2

解决方案


Mysql2 < 5 的 ActiveRecord,不支持可配置的参数来启用
ActiveRecord 4.2.6 中的prepared_statement 代码片段

连接适配器/mysql2_适配器.rb

module ConnectionAdapters
class Mysql2Adapter < AbstractMysqlAdapter
  ADAPTER_NAME = 'Mysql2'.freeze

  def initialize(connection, logger, connection_options, config)
    super
    @prepared_statements = false # No configurable param, default set to false
    configure_connection
  end
  ...
end

带有 Mysql2 = 5.2.1 适配器的 ActiveRecord 支持可配置参数以启用来自 ActiveRecord 5.2.1 的prepared_statement 代码片段

连接适配器/mysql2_适配器.rb

module ConnectionAdapters
class Mysql2Adapter < AbstractMysqlAdapter
  ADAPTER_NAME = "Mysql2".freeze

  include MySQL::DatabaseStatements

  def initialize(connection, logger, connection_options, config)
    super
    @prepared_statements = false unless config.key?(:prepared_statements)
    configure_connection
  end
  ...
end

因此,在 ActiveRecord 5.2.1 中,只需在 database.yml 中添加以下行即可启用prepared_statements

准备好的陈述:真


推荐阅读