LoginSignup
26
39

More than 5 years have passed since last update.

SQLServer: with(nolock)ヒントでロックを確実に回避できるという認識は間違い

Last updated at Posted at 2016-11-28

「nolock」なのでロックしないっしょ~と思いがちですが、その認識が間違っていたのでメモ。

SQLServerのロックについて

ロック モード
https://technet.microsoft.com/ja-jp/library/ms175519(v=sql.105).aspx

ロックの互換性
https://technet.microsoft.com/ja-jp/library/ms186396(v=sql.105).aspx

まずはロックについて。ロックにもいろいろ種類があるよっていう話と、同時に同一リソースにかけられるロックもあるよという話。
ここを一読すればだいたいつかめると思います。

名前忘れちゃったのですが、前に読んだ書籍に書いてあった、旗のイメージでロックを考えると分かりやすかったです。
Aの旗は同時に2本以上たてられるけど、Bの旗は1本しかたてられない。AとCの旗は一緒に立てられるけど、Dの旗は他のどの旗とも一緒には立てられない、、、みたいな。

with(nolock)をつけると何がおきているか

通常のSELECT文を発行すると、S-lock(共有ロック)が取得されます。こちらはdeleteなど発行した時のロック(X-lock)と競合するので、該当テーブルが更新中の場合はSELECTが待たされることになります。

with(nolock)をつけたSELECT文は、Sch-S lock(スキーマ安定度ロック)が取得されます。こちらはX-lockと競合しないので、更新中のテーブルでもSELECTできます。(※ダーティリード)

ということで、with(nolock)をつける=取得するロックをSch-Sロックにするということですね。
このロックはX-LockやU-Lockと競合しないため、確かにnolockなのですが、、、このSch-Sロックとも競合してしまう強力なロックがあります。

それがSch-M lock(スキーマ修正ロック)です。

インデックス付Viewを作成するとき(schema bindngしたViewにインデックス張るとき)や、transaction内でtruncateしたときなど、
Sch-Mロックが取得されます。

このSch-Mロックがかかると、該当リソースへのアクセスができなくなってしまうため、長時間Sch-Mロックが取得され続けるとタイムアウトエラーが頻発してしまいます。

他にもSch-Mロックが取得されるケースは存在するので、稼動しているDBに対してオンラインで何かしらの操作をする場合には、その操作によって取得されるロックの種類と、そのロックが取得されることによる影響をしっかりと開発環境で検証しておく必要があります。
うっかりSch-Mロックをかけてしまうと、(Sch-Mロックは長時間取得されるような重い操作が多いので)たっぷりタイムアウトエラーが発生しますので注意が必要です。

26
39
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
39