トランザクションで遊んでみた

何かデッドロックの一件でトランザクション分離レベルの変更を行ったけれど、イマイチこの分離レベルの詳細が分からないので、実験してみた。誰ですか、暇人だなんて言う人は。

=======================================================
【実験環境】
Windows7(32bit)
・SQLServer2005Express

【実験方法】

  1. クラスタインデックスと非クラスタインデックスを持ったテーブルを用意する。データは1万件を用意。
  2. VBSにて、対象テーブルに対してトランザクション開始→全件読み取り→待機→全件更新→待機→コミット……というスクリプトを書く
  3. VBSを起動し、全件読み取り後の待機まで進める。
  4. ManagementStudioにて、同じテーブルに対しトランザクションを張り、SELECT、INSERT、DELETE、UPDATEをそれぞれ発行してどのような動作になるか確認する。
  5. VBSを起動し、全件更新後の待機まで進める。
  6. ManagementStudioにて、同じテーブルに対しトランザクションを張り、SELECT、INSERT、DELETE、UPDATEをそれぞれ発行してどのような動作になるか確認する。

========================================================

ってなことをやってみた結果がこちら

※注1の補足:読み取りは出来るが、トランザクションAが更新を行っていないかのように表示される(スナップショットを読む為)。その為、Read_UnCommittedとは読み取り結果が異なる。

トランザクションAがVBSの処理、
トランザクションBがManagementStudioの処理です。

こうして見ると、読み取りに関する挙動を勘違いしていたなぁ。例えば、Read_Uncommittedでトランザクションを行った場合に、他のトランザクションから未コミット分の更新データの読み取りが出来るもんだと思っていたんだけれど、データ更新側ではなくて、データ読み取り側のトランザクションでRead_Uncommittedにする必要があったのね。

今回は表にしやすくするためにテーブル全件を対象にしたけれど、当然ロック範囲をもっと絞り込めば、ロック範囲外では更新だの追加だの行えました。(Repeatable_Readの※注2は、そのデータがロック範囲外であるからでしょうし)