MySQL SELECT FOR UPDATE Lock阻止所有线程?

时间:2013-01-31 14:41:16

标签: mysql ruby thread-safety sequel

我只是想知道mysql“SELECT FOR UPDATE”会锁定进程中的所有线程,如果需要在多线程应用程序中授予此锁定,请如何通过它。

为了简单起见,我只是在ruby中给出一个简单的测试代码:

t1 = Thread.new do
  db = Sequel.connect("mysql://abcd:abcd@localhost:3306/test_db")
  db.transaction do
    db["select * from tables where id = 1 for update"].first
    10.times { |t| p 'babababa' }
  end
end

t2 = Thread.new do
  db = Sequel.connect("mysql://abcd:abcd@localhost:3306/test_db")
  db.transaction do
    db["select * from tables where id = 1 for update"].first
    10.times { |t| p 'lalalala' }
  end
end

t1.join
t2.join
p 'done'

实际上,结果将是:

线程1和线程2挂起至少50秒后,其中一个线程获得“FOR UPDATE”LOCK(在Mysql设置中锁定等待时间为50秒),然后一个线程引发“超过锁定等待超时”错误并退出,另一个线程成功打印出'baba'或'lala'。

1 个答案:

答案 0 :(得分:2)

这与mysql驱动程序为每个查询锁定整个ruby VM的事实有关。当第二个线程点击FOR UPDATE锁定并冻结时,ruby中没有任何内容发生,直到它超时,从而导致你看到的行为。

安装mysqlplus gem(我没有阻止整个解释器,Sequel的mysql适配器将自动使用,如果已安装),或安装mysql2 gem并使用mysql2适配器而不是mysql适配器。