0

我只是想知道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 在其中一个线程获得“FOR UPDATE”LOCK 后挂起至少 50 秒(Mysql 设置中的锁定等待时间为 50 秒),然后一个线程引发“超出锁定等待超时”错误并退出,另一个线程成功打印出它的“baba”或“lala”。

4

1 回答 1

2

这与 mysql 驱动程序为每个查询锁定整个 ruby​​ VM 的事实有关。当第二个线程命中 FOR UPDATE 锁并冻结时,ruby 中什么都不会发生,直到超时,导致您看到的行为。

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

于 2013-01-31T16:51:10.380 回答