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 は、スレッドの 1 つが「FOR UPDATE」ロックを取得した後、少なくとも 50 秒間ハングし (ロック待機時間は Mysql 設定で 50 秒です)、1 つのスレッドが「ロック待機タイムアウトを超えました」エラーを発生させて終了します。別のスレッドが「baba」または「lala」を正常に出力します。

4

1 に答える 1

2

これは、mysql ドライバーがクエリごとに ruby​​ VM 全体をロックするという事実に関連しています。2 番目のスレッドが FOR UPDATE ロックにヒットしてフリーズすると、Ruby ではタイムアウトになるまで何も起こらず、表示されている動作が発生します。

mysqlplus gem をインストールするか (インタープリター全体をブロックするわけではなく、インストールされている場合は Sequel の mysql アダプターが自動的に使用されます)、または mysql2 gem をインストールして、mysql アダプターの代わりに mysql2 アダプターを使用します。

于 2013-01-31T16:51:10.380 に答える