【MySQL】トランザクションの分離レベルって?

はじめに

業務で複数トランザクションを走らせる処理をしていた時にふと、
「別トランザクションでINSERTされたデータをこのトランザクションでSELECTしたらどうしよう....」と不安になってしまいました。
そこでトランザクションの分離レベルについて調べたのでまとめていきたいと思います。

トランザクションとは

トランザクションとは、SELECTやUPDATEなど単一または複数のSQLクエリを含む一連の処理の単位を指します。
この単位でコミットやロールバックをする事ができます。

ACIDとは

innoDB 1トランザクション処理の特性のことです。

種類 説明
原子性(Atomicity) トランザクション内の処理は「全部処理される」か「全部処理されない」のどちらかである
一貫性(Consistency) トランザクションの前後でデータは整合性がとれている
分離性(Isolation) トランザクション実行中は他のトランザクションに影響を与えない
永続性(Isolation) トランザクションが完了すれば障害があってもデータは保持される

分離性という性質から、トランザクションは他トランザクションの変更の影響を受けないように互いに分離されています。
この分離性は分離レベルとして段階に分けられており、用途に応じて調整する事ができます。

分離レベルとは

トランザクションの変更が他のトランザクションでどのように見えるのか、トランザクション同士の影響レベルのことです。
MySQLではREPEATABLE READがデフォルトに採用されています。
OraclePostgreSQLSQL ServerではREAD COMMITTED。

🚩READ UNCOMMITTED
コミットされていない更新(UPDATE)・追加(INSERT)が他のトランザクションから見えてしまう状態です。
そのため、ダーティリード(コミット前のデータを参照する現象)を引き起こす可能性があります。
f:id:mmmnn1257:20181118173802p:plain

🚩READ COMMITTEDOraclePostgreSQLSQL Server
コミットされた更新(UPDATE)・追加(INSERT)が他のトランザクションから見えてしまう状態です。
コミット前のデータは参照できないのでダーティリードは起こりませんが、コミット後のデータは参照できるため、アンリピータブルリード/ファジーリード(コミット後の更新データを参照する現象)を引き起こす可能性があります。 f:id:mmmnn1257:20181118173452p:plain

🚩REPEATABLE READMySQL
コミットされた追加(INSERT)が他のトランザクションから見えてしまう状態です。
更新(UPDATE)に対しては他のトランザクションの影響を受けないため値そのものの整合性は保証されています。
しかし、追加(INSERT)については影響を受けてしまうため、ファントムリード(コミット後の追加データを参照する現象)を引き起こす可能性があります。
f:id:mmmnn1257:20181118173227p:plain

MySQLではファントムリードを防いでいます。

🚩SERIALIZABLE
トランザクションにロックをかけることで直列に扱っている状態です。
そのため、トランザクション内でSELECTされる値や数の整合性が保証されます。
しかし、同じデータに対して複数のトランザクションが変更を行う場合、一方のトランザクションは待機しければなりません。

おわりに

MySQLではREPEATABLE READを採用しており、さらにファントムリードも防いでいます。
そのため1つのデータに対して複数のトランザクションをかけていても特に気にする必要はなさそうです。

参考

データベースの信頼性と速度を左右する、トランザクション分離レベルについて
MySQLでトランザクションの4つの分離レベル
トランザクション分離レベルを理解するために実際に試してみる
MySQL 用語集


  1. データベースにおいてデータの読み書きを担当するストレートエンジン