私は次のような金融取引をしています(疑似):
begin
select record for update
update record(same record as selected)
insert another record into another table
commit
SELECT ... FOR UPDATE
トランザクション内で、トランザクションがコミットされた場合にのみ、特定の行のロックが解放されますか?
MySQL 5.0認定試験ガイドの418パラグラフ3によると
次のコマンドはトランザクションを破壊する可能性があります
ALTER TABLE
BEGIN
CREATE INDEX
DROP DATABASE
DROP INDEX
DROP TABLE
RENAME TABLE
TRUNCATE TABLE
LOCK TABLES
UNLOCK TABLES
SET AUTOCOMMIT = 1
START TRANSACTION
トランザクション内でこれらのコマンドを実行しない限り、トランザクションは安定しているはずです。実際、SELECT FOR UPDATEは非常に強力なので、行ロックはデータだけでなくインデックスにも侵入します。それは可能なInnoDBデッドロックを相殺することさえできました。私はかつてこの投稿でそれについて書いた: select for updateはインデックスされたカラムにエラーを与える
トランザクションを短く簡潔に保つ限り、SELECT FOR UPDATE
は問題ありません。トランザクションを断続的または予期しないデッドロックから保護する場合、MySQL 5.6には次のものが含まれます。
START TRANSACTION READ WRITE;
START TRANSACTION READ ONLY;
これらのようなオプションでトランザクションを開始する必要があります。どうして ?
そのMySQLドキュメント によると:
READ WRITEおよびREAD ONLY修飾子は、トランザクションアクセスモードを設定します。トランザクションで使用されるテーブルへの変更を許可または禁止します。 READ ONLY制限は、他のトランザクションから見えるトランザクションテーブルと非トランザクションテーブルの両方をトランザクションが変更またはロックすることを防ぎます。トランザクションは引き続き一時テーブルを変更またはロックできます。これらの修飾子は、MySQL 5.6.5以降で使用できます。
あなたの最後のコメントは
トランザクション内の行を更新用とは別の方法でロックできますか
SELECT ... LOCK IN SHARE MODE を実行することもできます。ドキュメントは言う
可能ですが、トランザクションは短くしてください。そうしないと、デッドロックの可能性が高まります。
誤解を解消するために、 MySQLのドキュメントからこれに注意してください :
LOCK IN SHARE MODE および FOR UPDATE クエリによって設定されたすべてのロックは、トランザクションがコミットまたはロールされるときに解放されますバック。
したがって、トランザクション内で SELECT ... LOCK IN SHARE MODE を実行すると、トランザクションがコミットまたはロールバックするまで、行はロックされたままになります。
また、例外ハンドラーがループ外にあり、トランザクションスコープがループ内にある場合でもLOOPは、mysqlが例外時にトランザクションを中断します。同じスコープのトランザクションが宣言されている場合は、例外ハンドラーを宣言する方が適切です。