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

こんにちは、ほろよい(@horoyoi_blog)です

今回はプログラミング初心者に向けて、トランザクションの分離レベルについてお話しします

  • トランザクションの分離レベルって何?
  • 分離レベルが違うと何がどうなるの?

そのような疑問をお持ちの方は是非参考にしてください!

簡潔に分かりやすくを心がけてまとめたので参考にしてもらえれば幸いです

トランザクション分離レベルとは?

トランザクションの分離レベルというのは、ACID性の1つである「分離性」をどの程度まで許容するか、分離性の程度のことを表しています

ACID性とは?

ACID性とは、トランザクションが持つべき4つの性質のことです

  • 原子性 (Atomicity)
  • 一貫性 (Consistency)
  • 分離性 (Isolation)
  • 耐久性 (Durability)

原子性:トランザクションに含まれるタスクが全て実行されるか、あるいは全く実行されないことを保証する性質

一貫性:トランザクション開始と終了時にあらかじめ与えられた整合性を満たすことを保証する性質

分離性:トランザクション中に行われる操作は他のトランザクションに影響を与えないという性質

耐久性:トランザクションの結果は障害が発生した時も失われてはいけないという性質

分離レベルの種類

トランザクションの分離レベルは以下の4種類に分けられます

下に行くほど(分離レベルが高いほど) 整合性・一貫性のレベルは高くなりますが、並列処理性能は低くなります

  • READ UNCOMMITTED (リードアンコミット)
  • READ COMMITTED (リードコミット)
  • REPEATABLE READ (リピータブルリード)
  • SERIALIZABLE (シリアライザブル)

MySQLのデフォルト分離レベルはREPEATABLE READ, PostgreSQLやSQLserverはREAD COMMITTEDです

「整合性・一貫性のレベルは高くなりますが、並列処理性能は低くなります」

ここについて具体的にどういうことか、簡単に検証して解説します!

検証1:分離レベルが高いほど、整合性・一貫性のレベルは高くなる

「整合性・一貫性のレベルは高くなる」とは具体的にどういうことかを READ COMMITED とREPEATABLE READ を例に説明します

それぞれの分離レベルで以下の操作を行います

  1. トランザクションA(緑文字)からusersテーブルのレコード(id=2645)をSELECT
  2. トランザクションB(紫文字)から同じレコードをUPDATE
  3. トランザクションA(緑文字)から再度SELECT

結果は次の通りです

READ COMMITTEDの場合

REPEATABLE READの場合

見てわかる通り、READ COMMITEDの場合、トランザクションBでコミットされた変更を読み取るため、SELECTの結果が1回目(20)と2回目(21)で変わっています

このように他のトランザクションでコミットされた変更を読み取る現象をファジーリード※と呼びます

※ノンリピータブルリードと呼ばれることもあります

一方、REPEATABLE READ の場合、トランザクションBからの変更を読み取らないので、SELECTの結果が1回目(21)と2回目(21)で同じになっています

この結果からも分かるように、分離レベルが高いほど一貫性が保証されるようになっているのです!

検証2:分離レベルが高いほど、並列処理性能は低くなる

続いて「並列処理性は低くなる」とは具体的にどういうことかを SERIALIZABLE と REPEATABLE READ を例に解説します

それぞれの分離レベルで以下の操作を行います

  1. トランザクションA(緑文字)からusersテーブルのレコード(id = 2645)をSELECT
  2. トランザクションB(紫文字)から同じレコードをUPDATE

結果は次の通りです

SERIALIZABLEの場合

REPEATABLE READの場合

見て分かる通り、SERIALIZABLEの場合はトランザクションAがコミットされるまでトランザクションBのUPDATEが実行されませんでした

これはなぜかと言うと、SERIALIZABLEの場合はSELECTする行に対して行ロックをかけるため、他のトランザクションからの更新はロックが解放されるまで待たされるのです

一方、REPEATABLE READの場合はSELECT時に行ロックをかけないので他のトランザクションからも即更新することができるのです

この実験結果からも分離レベルが高いほど並列処理性が低くなるということがなんとなくでも分かって頂けたかと思います

ほろよい
ほろよい

なので分離レベルを決める時は、データベースを利用するアプリケーションが一貫性と並列処理性どちらを重視するのかを検討する必要があります

分離レベルと起こりうる現象

上で「ファジーリード」が出てきましたが、分離レベルによっては、他にも「ダーティーリード」や「ファントムリード」という読み取りの現象が発生します

分離レベルと起こりうる現象は以下のようになっています

分離レベルダーティーリードファジーリードファントムリード
READ UNCOMMITED発生する発生する発生する
READ COMMITED発生しない発生する発生する
REPEATABLE READ発生しない発生しない発生する
SERIALIZABLE発生しない発生しない発生しない

いまいちイメージがつかないと思うので、それぞれの現象を確かめながら簡単に解説します

ダーティーリード

ダーティリードはあるトランザクションが更新している最中に、他のトランザクションがコミットされていない変更を読み取れてしまう現象のことを指します

以下の操作を行って実際に確かめてみます

  1. トランザクションAでUPDATE (コミットはしない)
  2. トランザクションBでSELECT

結果は以下のようになりました

READ UNCOMMITEDの場合

REPEATABLE READの場合

READ UNCOMMITEDの場合はトランザクションAでコミットされていない変更をトランザクションBから読み取れてしまっていること(ダーティリード)が確認できました

ファジーリード(ノンリピータブルリード)

ファジーリードはあるトランザクションが更新している最中に、他のトランザクションが変更を読み取れてしまう現象のことを指します

以下の操作を行って実際に確かめてみます

  1. トランザクションAでUPDATE
  2. トランザクションBでSELECT
  3. トランザクションAでCOMMIT
  4. トランザクションBでSELECT

結果は以下のようになりました

READ COMMITTEDの場合

REPEATABLE READの場合

READ COMMITTEDの場合はトランザクションAでコミットされた変更をトランザクションBから読み取れてしまっていること(ファジーリード)を確認できました

まとめ

MySQLの分離レベルについて私なりにまとめてみました

この記事では基本中の基本だけ解説しているので、もっと詳しく知りたい方はMySQL公式ドキュメントや他の方の記事を読んで理解を深めてください

この記事がプログラミング初心者の方の参考になれば嬉しく思います

最後まで読んで頂きありがとうございました

良ければ他の記事もどうぞ!

【MySQL】ロックとは?共有ロック,排他ロックの違いや行ロックの種類を解説

MySQL初心者におすすめの書籍

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です