0

何が起こっているかの基本的な考え方は次のとおりです。

begin transaction
some_data=select something from some_table where some_condition;
if some_data does not exists or some_data is outdated
  new_data = insert a_new_entry to some_table
  commit transaction
  return new_data
else
  return some_data
end

複数のプロセスが上記のコードを同時に実行すると (クライアントが同じ要求を同時に多数発行する場合など)、実際には 1 つしか必要ないのに、多数の「new_data」が挿入されます。

これは並行性の非常に典型的なシナリオだと思いますが、それでもそれを回避する適切な方法がわかりません。select_or_insert ジョブを実行するための単一のワーカー プロセスを持つことや、分離レベルを Serializable(unacceptable) に設定することなど、私が考えることができることです。しかし、どちらも私にはまったく満足のいくものではありません。

PS: データベースは mysql、テーブル エンジンは innodb、分離レベルは反復可能読み取りです。

4

1 に答える 1

0

イニシャルSELECTでは、 を使用しますSELECT ... FOR UPDATE

これにより、トランザクションがコミットされる (またはロールバックされる) まで、他のクライアントがレコードを読み取らないようにレコードがロックされるため、クライアントはSELECTコマンドを待機し、最初のクライアントが完了するまで残りのロジックに進みませんUPDATE

ROLLBACK状態でトランザクションを実行する必要があることに注意してください。そうしないとelse、接続が切断されるまでロックがブロックされ続けます。

于 2012-05-29T18:49:40.847 に答える