【问题标题】:Rails ActiveRecord connection sessionRails ActiveRecord 连接会话
【发布时间】:2016-04-19 12:31:24
【问题描述】:

我在 Rails 3.2 + mySQL 应用程序中有以下代码:

ActiveRecord::Base.connection.execute("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED")
ActiveRecord::Base.transaction do
              @book = ActiveRecord::Base.connection.execute("select * from books limit 1")
end

据我了解,第一条语句将导致同一会话中的下一个事务处于“READ UNCOMMITTED”隔离状态,然后隔离将恢复为默认值。

我的问题是:我能否确定事务块将始终在同一个会话中执行?另外,我能否确定在第一条语句和第二条语句之间的同一会话中不会发生其他事务?

我尝试在 Google 上搜索这个主题,但由于我是 Rails 新手,所以我找不到任何可以让我清楚这一点的解释。任何帮助将不胜感激!

谢谢!

【问题讨论】:

    标签: mysql ruby-on-rails activerecord rails-activerecord transaction-isolation


    【解决方案1】:

    我认为您的所有问题都可以通过“是”来回答。即使在 Rails 3.2 中,与数据库的连接也是由connection pool 管理的。该池确保每个线程都有自己的专用连接到数据库。池根据每个线程唯一的线程 ID 将连接分配给线程。阅读docs了解更多信息。

    所以我认为两个线程不可能同时共享一个连接和一个 MySQL 会话。此外,应保证事务将始终使用与隔离级别设置代码相同的连接(即在同一会话中)调用。

    顺便说一句,如果您使用的是 Rails 4 或更高版本,您可以仅使用 transaction 方法实现相同的行为。不幸的是,Rails 3 不支持以这种方式设置隔离级别。因此,以下示例实际上不适用于您的特定场景:

    Book.transaction(:isolation => :read_uncommitted) do
      @book = Book.first
    end
    # => SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    #    BEGIN
    #      SELECT  `books`.* FROM `books`  ORDER BY `books`.`id` ASC LIMIT 1
    #    COMMIT
    

    【讨论】:

    • 谢谢。这有帮助!是的,Rails 4 似乎对此有更好的解决方案,但不幸的是,我现在无法使用当前项目迁移到 Rails 4。
    • 一个后续问题:是否有必要像我在代码中那样将语句包装在事务块中?如果我只执行没有事务块的sql语句,隔离是否仍然可以正常工作?
    • 是的,正如here解释的那样,隔离设置对下一个事务块有效。即使设置会话级隔离,也仅对所有后续事务块有效。
    猜你喜欢
    • 2011-07-11
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    相关资源
    最近更新 更多