Rails ActiveRecord连接会话

时间:2016-04-19 12:31:25

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

我在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"隔离然后隔离将返回默认值。

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

我尝试谷歌这个话题,但由于我是Rails的新手,我无法找到任何可以让我清楚的解释。任何帮助将不胜感激!

谢谢!

1 个答案:

答案 0 :(得分:3)

我认为您的所有问题都可以通过" YES" 来解答。即使在Rails 3.2中,与数据库的连接也由connection pool管理。此池确保每个线程都有自己的专用连接到数据库。池根据线程ID为线程分配连接,这些线程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