トランザクションに関わる3つの副作用(ダーティーリード/反復不能読み取り/ファントムリード)

DB

MySQLなどのデーターベースを扱うときに、DBに対して複数の処理が要求される場合に発生しうる3つの副作用を整理しました。

ダーティーリード(Dirty read)

コミットされていない変更を、他のユーザーが読めてしまう副作用のこと。
※コミットとは、DB書き換えを確定させるアクションのことをいいます

例えば、AさんがATMで出金をしようとして、何らかの原因で処理が中断され、ロールバックされるが、その間にB社がAさんの口座から、”まだコミットされてない残高”から引き落としをしてしまうような事象です。

Aさんからすると、出金をしていないのに出金されたことになっており、さらにB社から引き落としがなされていることになってしまい、かなりマズい副作用となってしまいます…。

反復不能読み取り(Non repeatable read)

データの整合性が合わなくなってしまう不具合です。
例えば、ユーザーAがある情報を修正してupdateのSQL処理をしたとして、ユーザーBが同じ情報をupdateのSQLの処理前後に閲覧しようとすると、結果が変わってしまいます。
予約サイトなどであると思いますが、先ほどまでは空席があったのにリロードすると席が埋まってしまうような事象があります。

ファントムリード(Phantom read)

反復不能読み取りと似ています。
同じテーブルから何度か読み込みをしていく場合に、別のトランザクションによるレコードの追加が反映されてしまい、同じトランザクション中なのに結果数が変わってしまう副作用です。

副作用を回避するために(トランザクションの分離)

上記の副作用はトランザクションによって解決することができます。
DBMSは、分離性があるとも言え、他のトランザクションを同時に実行していたとしても単独で実行している結果としてくれます。

仕組みとしては、ロックと呼ばれてあり、読み書きしている行にさらに読み書きができないようになっているそうです。

通常数ミリ秒以下とのごく短い時間となりますが、ロックが沢山発生するとDBの動作が即なってしまう原因となるので気をつける必要があります。

多くのDBMSではトランザクションを分離するかレベルが4つに分けられていて、

・READ UNCOMMITED
・READ COMMITED
・REPEATABLE READ
・SERIALIZABLE

があり、下になるほど安全になるが低速の処理となります。

デフォルトではREAD COMMITEDと設定されており、ダーティリードは回避できるが、反復不能読み取りとファントムリードは発生する可能性がある状態となっています。(が、一般的にはREAD COMMITEDで十分とされています。必要に応じて設定の検討が出てくると思います)

コメント

タイトルとURLをコピーしました