Memo

メモ > 技術 > データベース: MySQL > トランザクション

トランザクション
■トランザクション ・BEGIN または START TRANSACTION でトランザクションを開始する(意味はどちらも同じ) ・COMMIT でトランザクションを終了し、変更は永続化される ・ROLLBACK でトランザクションを終了し、変更は取り消される ■トランザクション分離レベル MySQLのInnoDBのトランザクション分離レベルは、デフォルトで REPEATABLE READ となっている REPEATABLE READ はトランザクション開始後にテーブルの値を変更しても、SELECT で参照できるのは変更前の値 これにより、例えば予約システムなどで 1. トランザクションを開始する 2. 現在の予約数を取得する 3. 取得した予約数が一定件数以下なら予約データを登録する。一定件数以上ならエラーにする という処理を書いたとき、2で取得できるデータは1時点のもの つまり3に到達した時点で予約数はさらに増えている可能性がある つまり「定員が100人のイベントに105人予約されてしまった」という現象が起こりうる トランザクション分離レベルを「READ COMMITTED」にしておけば、操作もとでコミットされた時点で他端末からも変更後の値を参照できるようになり、Oracle、PostgreSQL、SQL Server などではこれがデフォルト設定となっている そちらの方が直感的なので、変更しておくと余計なトラブルを防ぐことができる(常に変更して良いものかは要検討) 以下のSQLを発行することで、その接続だけトランザクション分離レベルを変更できる
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
MySQLでトランザクションの4つの分離レベルを試す - FAT47の底辺インフラ議事録 http://d.hatena.ne.jp/fat47/20140212/1392171784 MySQLのデフォルトのトランザクション分離レベルは SELECT がスナップショットを参照する - ngyukiの日記 http://ngyuki.hatenablog.com/entry/2013/02/02/202558 [RDBMS][SQL]トランザクション分離レベルについて極力分かりやすく解説 - Qiita https://qiita.com/PruneMazui/items/4135fcf7621869726b4b InnoDBにおけるトランザクション分離レベルについて - Qiita https://qiita.com/taisho6339/items/1097c67a54cedf9504d6 現在のトランザクション分離レベルは、以下のSQLで確認できる
SELECT @@GLOBAL.tx_isolation, @@tx_isolation;
第47回 トランザクション分離レベルを変更する:MySQL道普請便り|gihyo.jp … 技術評論社 https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0047 MySQLのautocommitとトランザクション分離レベルのメモ - Qiita https://qiita.com/rubytomato@github/items/562a1638191aacaeb333 MySQLがこのような挙動になっているのは、バイナリログの整合性を担保するための名残らしい MySQL InnoDBのネクストキーロック おさらい - SH2の日記 http://d.hatena.ne.jp/sh2/20090112 以下、トランザクション分離レベルの挙動を検証したときのメモ 2つの端末からアクセスするので、それぞれ「mysql1>」「mysql2>」と表記する ■REPEATABLE READ のまま(デフォルト)
mysql1> BEGIN; mysql2> BEGIN; mysql1> SELECT * FROM test; mysql1> UPDATE test SET text = 'TEST2 UPDATED!' WHERE id = 2; mysql1> SELECT * FROM test; … 更新を確認できる mysql2> SELECT * FROM test; … 他端末からは更新を確認できない mysql1> COMMIT; mysql2> SELECT * FROM test; … 他端末からは更新を確認できない mysql2> COMMIT; mysql2> SELECT * FROM test; … 他端末からも更新を確認できる
■READ COMMITTED に変更
mysql1> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; mysql1> BEGIN; mysql2> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; mysql2> BEGIN; mysql1> SELECT * FROM test; mysql1> UPDATE test SET text = 'TEST2 UPDATED!' WHERE id = 2; mysql1> SELECT * FROM test; … 更新を確認できる mysql2> SELECT * FROM test; … 他端末からは更新を確認できない mysql1> COMMIT; mysql2> SELECT * FROM test; … 操作もとでコミットされた時点で、他端末からも更新を確認できる
■ロールバック 【忘備録】InnoDBでもロールバックが効かない文 http://mementomori.info/%E3%80%90%E5%BF%98%E5%82%99%E9%8C%B2%E3%80%91innodb%E3%81%A7%E3%82%82%E3%83%... MySQLでTruncateはRollback出来るのか? | SRIA BLOG - 宮城県仙台市のWEBシステム開発・スマホアプリ開発 https://www.sria.co.jp/blog/2014/08/mysql-can-do-rollback-truncate/ MySQLの「暗黙のトランザクションコミット」対策:トランザクション中でも安全にCREATE TABLEなどをする方法 - Qiita https://qiita.com/suin/items/3527297a22632f3db31d MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.3.3 暗黙的なコミットを発生させるステートメント https://dev.mysql.com/doc/refman/5.6/ja/implicit-commit.html

Advertisement