トランザクション分離レベル
分離レベルの種類
Serializable
複数並行に動作するトランザクションそれぞれの結果が、逐次実行した場合と同じ結果になる
Repeatable Read
InnoDBのデフォルト
同一トランザクション内では最初のreadと結果がトランザクション内で変わらない
レコード数の結果が変わることがある
-> Phantom read が発生
ただし InnoDBではこれは発生しない
Read Committed
MySQL以外の多くのDBMS (PostgreSQL, Oracle, SQL Server等)のデフォルト
別のトランザクションでコミット済みの変更を読み取れてしまう
トランザクション内でタイミングによってreadの結果が変わることがある
-> Phantom read, Fuzzy read が発生
Read Uncommitted
別トランザクションで未コミットの変更が読み取れてしまう
-> Phantom read, Fuzzy read, Dirty read が発生
発生しうる問題
Dirty read
別のトランザクションでコミットされていないデータが見える
Fuzzy read / Non-Repeatable read
別のトランザクションで特定の行を更新/削除したとき、その行の更新/削除が見える
Phantom read
別のトランザクションで特定の行の集合を追加/削除したとき、その結果が見える
Lost Update
複数トランザクションで同じ行に更新をかけたとき、後に更新をかけたトランザクションの結果だけ反映される
ロックの種類
Shared Lock
Shared Lock のみ可
Exclusive Lock
Shared/Exclusive Lock どちらも不可
上記の問題を防ぐには (TODO)
MySQL (InnoDB)
デフォルトで Repeatable Read
トランザクション内で SELECT FOR UPDATEを利用してreadする
whereで指定した行にロックをかける (gap lock, next-key lock をかけることもある)
PostgreSQL
Serializable のDBMSを使う
Cloud Spanner (正確にはSerializableより強固な External Consistency (= 外部整合性))
rw transaction 内で行ロックを取ってから行を更新する
ref
MySQL
https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html
https://dev.mysql.com/doc/refman/8.0/en/innodb-next-key-locking.html
https://lukesilvia.hatenablog.com/entry/20110123/p1