READ COMMITTED
このトランザクションは,REPEATABLE READ
で説明したファントムリードになります。
ファジーリードはファントムリードとよく似ています。たとえば,
READ COMMITTEDの挙動
ここではファントムリードとファジーリードが起こることを確認してみましょう。以下のようにトランザクション分離レベルを変更します。
txA> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; txB> SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
ファントムリードから確認してみましょう。txAでトランザクションを開始します。
txA> BEGIN; Query OK, 0 rows affected (0.00 sec) txA> SELECT * FROM user; +--------+-------+ | name | point | +--------+-------+ | sato | 0 | | suzuki | 0 | | tanaka | 0 | +--------+-------+ 3 rows in set (0.00 sec)
userテーブルに3件のデータが入ってることがわかります。ここでtrBでデータの挿入を行います。
txB> INSERT INTO user (name, point) VALUE('takahashi', 0); Query OK, 1 row affected (0.00 sec)
この時にtrAに戻り,
txA> SELECT COUNT(*) FROM user; +-----------+-------+ | name | point | +-----------+-------+ | sato | 0 | | suzuki | 0 | | tanaka | 0 | | takahashi | 0 | +-----------+-------+ 4 rows in set (0.00 sec)
こちらではユーザが4件となっていて,
続いてファジーリードを試していきます。txAで一旦コミットをしてもう一度トランザクションを作成し,
txA> COMMIT; txA> BEGIN; txA> SELECT point FROM user WHERE name = 'sato'; +-------+ | point | +-------+ | 0 | +-------+ 1 row in set (0.00 sec)
現在satoさんのpointは0であることがわかりました。ここで,
txB> UPDATE user SET point=100 WHERE name='sato'; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0
ここでtxAに戻り確認してみましょう。
txA> SELECT point FROM user WHERE name = 'sato'; +-------+ | point | +-------+ | 100 | +-------+ 1 row in set (0.00 sec) txA> COMMIT;
txAのトランザクションの中でも更新された値が入っていることから,
最後に,REPEATABLE READ
で同じことを行った場合にどうなるかを簡単に確認してみましょう。
txA> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; txB> SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; txA> BEGIN; txA> SELECT point FROM user WHERE name = 'sato'; +-------+ | point | +-------+ | 0 | +-------+ 1 row in set (0.00 sec) txB> BEGIN; txB> UPDATE user SET point=100 WHERE name='sato'; txB> COMMIT; txA> SELECT point FROM user WHERE name = 'sato'; +-------+ | point | +-------+ | 0 | +-------+ 1 row in set (0.00 sec) txA> COMMIT; txA> SELECT point FROM user WHERE name = 'sato'; +-------+ | point | +-------+ | 100 | +-------+ 1 row in set (0.00 sec)
上記のように,REPEATABLE READ
の場合はトランザクション中ではSELECTステートメントが同じ値を返していることがわかります。
READ UNCOMMITTED
このトランザクション分離レベルは,
ただ,
また,
READ UNCOMMITTEDの挙動
ここではダーティリードについて確認してみましょう。以下のようにトランザクション分離レベルを設定します。
txA> SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; txB> SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
続いて,
txA> BEGIN; txA> SELECT point FROM user WHERE name = 'suzuki'; +-------+ | point | +-------+ | 0 | +-------+ 1 row in set (0.00 sec)
現在0ポイントであることがわかりました。そこでtxBでトランザクションを作成し,
txB> BEGIN; txB> UPDATE user SET point=2000 WHERE name='suzuki'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
まだコミットをしていないため更新は確定していませんが,
txA> SELECT point FROM user WHERE name = 'suzuki'; +-------+ | point | +-------+ | 2000 | +-------+ 1 row in set (0.00 sec)
上記のようにtxAの中で確定されていない変更も読めてしまうため,
各トランザクション分離レベルのまとめ
最後にMySQLのInnoDBで,
ダーティリード | ファジーリード | ファントムリード | |
---|---|---|---|
SERIALIZABLE | 発生しない | 発生しない | 発生しない |
REPEATABLE READ | 発生しない | 発生しない | 発生しない |
READ COMMITTED | 発生しない | 発生する | 発生する |
READ UNCOMMITTED | 発生する | 発生する | 発生する |
まとめ
今回はトランザクション分離レベルの挙動について紹介しました。トランザクション分離レベルでは,