0

I just wonder mysql "SELECT FOR UPDATE" lock block all my threads in a process, and how to by pass it if I need to grant this lock in multi-threaded Applications.

To keep it simple, I just give a simple test code in 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'

Actually, the result will be:

thread 1 and thread 2 hang for at least 50 sec after one of the thread get the "FOR UPDATE" LOCK ( Lock wait time is 50 sec in Mysql Setting ), and then one thread raise "Lock wait timeout exceeded" error and quit, another thread successfully print its 'baba' or 'lala' out.

spencer7593
  • 106,611
  • 15
  • 112
  • 140
Simon Iong
  • 191
  • 3
  • 9

1 Answers1

2

This is related to the fact that the mysql driver locks the entire ruby VM for every query. When the second thread hits the FOR UPDATE lock and freezes, nothing in ruby happens until it times out, causing the behavior you are seeing.

Either install the mysqlplus gem (which I doesn't blocks the entire interpreter, and Sequel's mysql adapter will use automatically if installed), or install the mysql2 gem and use the mysql2 adapter instead of the mysql adapter.

Jeremy Evans
  • 11,959
  • 27
  • 26