我只是想知道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'。
答案 0 :(得分:2)
这与mysql驱动程序为每个查询锁定整个ruby VM的事实有关。当第二个线程点击FOR UPDATE锁定并冻结时,ruby中没有任何内容发生,直到它超时,从而导致你看到的行为。
安装mysqlplus gem(我没有阻止整个解释器,Sequel的mysql适配器将自动使用,如果已安装),或安装mysql2 gem并使用mysql2适配器而不是mysql适配器。