私は here から回答を読んでいました(stackoverflowから、ここで尋ねるべきだと思います)
NOLOCKは、ロックをまったく配置しないことを意味します。
クエリは、単一のクエリでUPDATE前のデータの一部とUPDATE後の一部を返す場合があります。
Nolockはテーブルにロックを設定しないので、他の人が同時にクエリを実行できます。
それが示す答えと例から、データの更新中にデータをフェッチします。
なぜそれが起こるのですか?
通常の選択ではテーブルをロックしようとするので、updateステートメントを実行すると、行またはページがロックされます。次に、selectステートメントを実行しようとすると、updateステートメントのロックが解除されるまでロックをかけることができません。
しかし、この場合、selectステートメントはテーブルをロックしようとしないため、updateステートメントがロックを解放するのを待たずに実行できますか?
NOLOCK
がロックをまったく配置しないことを意味することは、必ずしも正しくありません。このヒントの下のクエリは、Sch-S
ロックと( おそらくHOBT
ロック)をとります。
read committed
分離レベルでは、SQL Serverは( 通常 )行レベルのS
ロックを取得し、データが読み取られるとすぐにそれらを解放します。これらは、コミットされていない更新で保持されているX
ロックと互換性がないため、ダーティリードを防ぎます。
リンクされた回答の例では、SELECT
クエリは変更された行を検出してもブロックされないため、部分的な更新を読み取る可能性が高くなります。
デフォルトのread committed
分離レベルでも発生する可能性がありますが、SELECT
は「before」の値を持つ行と「after」の値を持つ行を読み取ります。必要なのは、
R1
の値を読み取り、そのS
ロックを解放しますR2
を更新し、X
ロックを取得しますR2
を読み取ろうとし、ブロックされます。R1
を更新し、X
ロックを取得します。R2
を読み取れるようになりますこのタイプの状況は、たとえば、SELECT
とUPDATE
が目的の行を見つけるために異なるインデックスを使用している場合に発生する可能性があります。
例
CREATE TABLE T
(
X INT IDENTITY PRIMARY KEY,
Y AS -X UNIQUE,
Name varchar(10),
Filler char(4000) DEFAULT 'X'
)
INSERT INTO T (Name)
SELECT TOP 2500 'A'
FROM master..spt_values
今度は1つのクエリウィンドウで
DECLARE @Sum int
SELECT 'SET @@ROWCOUNT' WHERE 1=0
WHILE (@@ROWCOUNT = 0)
SELECT @Sum = SUM(LEN(Name))
FROM T
WHERE Y IN (-1, -2500)
HAVING SUM(LEN(Name)) = 3
これは無限ループで実行されます。別の実行で
UPDATE T
SET Name=CASE WHEN Name = 'A' THEN 'AA' ELSE 'A' END
これにより、他のクエリのループが停止する可能性があります(そうでない場合は再試行します)。つまり、A,AA
またはAA,A
のいずれかを読み取る必要があります。
ヒントNOLOCK
は、トランザクション分離レベルREAD UNCOMMITTED
と同等で、1つのテーブルアクセスメソッドのスコープに制限されています。
コミットされていない結果セットを結果セットに表示するRUは何ですか?うーん、実際には「しないこと以下で説明します。
まあ(これはかなり単純化されていると思います)MSSQL(デフォルトの動作)はロックエンジンです。つまり、ロックを使用して、一貫した方法でデータを読み書きします。この単純化された説明では、MSSQLは2種類のロックを使用します:共有ロックと排他ロック。
共有(S)ロックは、リソース(行、行のページ、またはテーブル全体)の読み取りを許可しますが、リソースへの書き込みは許可しないロックです。したがって、トランザクションT1がS1ロックをR1行に置くと、R1を読み取ろうとするすべてのトランザクションがその読み取りを取得しますが、Sロックが有効な間は誰もR1に書き込むことができません。
排他(X)ロックは、共有ロックに対応するロックです。これは、リソースへの排他的アクセスを許可します-Xロックを取得したトランザクションを除いて、他のトランザクションは読み書きできません。上記の例で、T1がS1ロックではなくXロックをR1で取得した場合、T1以外の誰もそれを読み書きすることはできません。
それはテオリーです。分離レベルはロックを尊重し、その普及と特性を尊重します。 READ UNCOMMITTED
を除くすべて。これは、読み取りに関するロックに*(ここでお好みの悪口を言う)をロックに与えます。それでも、別のトランザクションがXロックを取得した行を更新することはできません。それは単に言います:"クエリプランに関連するすべてのものを読みます-その上にあるロックは無視してください。"そして、それを行います。