次の 2 つの MySQL ステートメントを実行します。
1) SELECT * FROM table1 WHERE field1=val1 FOR UPDATE;
2) UPDATE table1 SET field2=val2 WHERE field1=val1;
2 番目のステートメントが、最初のステートメントによって返された行を正確に変更することが重要です (追加の行や 1 つ少ない行はありません)。したがって、トランザクションを auto_commit=false で実行し、select ステートメントの「for update」バージョンを使用します。
「For Update」は、返されるすべての行をロックするため、2 番目のステートメントが実行されたときに元の状態になります。しかし、挿入はどうですか?別のスレッドが field1=val1 の間に新しい行を挿入し、2 番目のステートメントによって変更される可能性はありますか?
もう 1 つの質問: 2 番目のステートメントが行自体を変更するのではなく、次のようなことを行う場合、違いはありますか?
3) INSERT INTO table2 (SELECT * FROM table1 WHERE field1=val1)
(3) が (1) と同じトランザクションにある場合、両方の選択がまったく同じ要素を返すことが保証されますか?
編集:
私は InnoDB を使用しており、次のキーのロックとギャップのロックに関するいくつかの記事を読みました。私の知る限り、(1) の実行中、InnoDB は選択された行だけでなく、アクセスされたインデックスもロックしていました。
では、列「field1」にインデックスがある場合、この問題は発生しないと言うのは正しいでしょうか? インデックスがない場合はどうなりますか?じゃあ違うの?