トランザクション分離レベル
- RR(Repeatable Read)
- 複数回のクエリの間に他トランザクションがコミットしていてもその内容を反映されない
- ファントムリードが起きる。ただしInnoDBではMVCCのため発生しない。
- MySQLのデフォルトのトランザクション分離レベル
- RC(Read Commited)
- クエリ実行時点でCommitされたデータを読み込む。
- ファントムリードと、ファジーリードが発生する
- Oracle、PostgreSQL、SQL Serverのデフォルトのトランザクション分離レベル
ロックタイムアウトとデッドロック
ロックタイムアウト
- ロック状態:更新処理が同時に行われたときに、先に行われる更新を待っている状態のこと。
- ロックタイムアウト:ロック待ち状態で設定のロック待ち時間を超えること。システム変数
innodb_rollback_onn_timeout
で待ち時間を設定できる。 - タイムアウトエラー時は、エラーが出たクエリのみロールバックされる。トランザクション全体をロールバックしたい場合は、明示的に
ROLLBACK
を発行する必要がある。
デッドロック
- デッドロック:互いにテーブルのロックを保持したまま、もう一方のテーブルに対してロックが必要な処理が行われるとき、ロックが解除されない状態
デッドロックが起きたら
- 上限を決めたリトライ処理を行う。
デッドロックを起こさないために
- トランザクションを小さくコミットする。
- 処理を行うテーブルの順序を決める。
- 必要がない場合にロック読み取りの利用を避ける。
- トランザクションの分離レベルを
READ COMMITTED
にする - テーブル単位のロックを取得して更新を直列化する。(並列に処理が行えなくなるデメリットあり)
- インデックスを利用する。(インデックスがないと、スキャンした行全体にロックが掛かる)
参考
- 『おうちで学べる データベースんの基本』 ミックら著
- MySQLのMVCC - Qiita
- トランザクション分離レベルについてのまとめ - Qiita