編集:@MaxVernonが指摘しているように、以下はNOLOCKを使用する提案ではありません。トランザクションレベルを設定することについて言及し、最初に立ち上げるREAD UNCOMMITED
よりも否定的な意味合いをそのままにしておくべきNOLOCK
です。最初に投稿されたように:
迅速かつ簡単なのは、「はい、特定のインデックスヒントが指定されていない場合(NOLOCK、「ダーティリード」と呼ばれることもあります)または2番目のクエリのトランザクション分離レベルがREAD UNCOMMITED
(まったく同じように動作する)に設定されていない限り、最初のクエリは2番目のクエリをブロックします、いいえ、違います。"
相互排他的であるかそうでない場合、WITH
2番目の句を含めることを伴う質問で提供される追加の詳細に応じて、SELECT
2つのクエリ間の相互作用はほぼ同じになります。
IF NOT EXISTS ( SELECT 1
FROM sys.objects
WHERE name = 'Foo'
AND type = 'U' )
BEGIN
--DROP TABLE dbo.Foo;
CREATE TABLE dbo.Foo
(
Foo_PK BIGINT IDENTITY( 1, 1 ) NOT NULL,
PRIMARY KEY ( Foo_PK ),
Bar BIT,
x BIT,
y BIT,
z BIT
);
CREATE NONCLUSTERED INDEX IX_Foo_x
ON dbo.Foo ( x );
INSERT INTO dbo.Foo ( Bar, x, y, z )
VALUES ( 1, 1, 1, 1 ), ( 0, 0, 0, 0 );
END;
GO
BEGIN TRANSACTION;
UPDATE dbo.Foo
SET y = 0
WHERE x = 1;
-- COMMIT TRANSACTION;
別のセッションで、次を実行します。
SELECT *
FROM dbo.Foo WITH ( NOLOCK );
GO
SELECT *
FROM dbo.Foo;
sp_lock
できればさらに別の別のセッションで実行すると、現在保持されているロックを調べることができます。
EXECUTE dbo.sp_lock;
他の(Intent-Exclusive)ロックと混同しないように、(排他的)モードでKEY
挿入トランザクションを実行するspidによって型ロックが保持されているのが見えるはずです。ロックドキュメントはながらことを示すロックレンジ特有であり、それはまた、データを変更することによって影響を受けた列を挿入または更新し、他のトランザクションを防ぎ、その中にそれが元のクエリの範囲内に入ることができることを含んでいました。保持されているロック自体は排他的であるため、最初のクエリは、他の同時トランザクションからリソースへのアクセスを妨げています。実際には、列のすべての行は、最初のクエリで指定された範囲内にあるかどうかに関係なくロックされます。 X
IX
KEY
S
ロックは、このように第二のセッションであろう保持されるWAIT
まで、X
別の予防、ロッククリアX
(又はU
第二セッションの存在を正当化し、その読み出し動作を完了する前に、異なる同時SPIDからそのリソース上で取られるの)ロックをS
ロックします。
ここで明確にするための編集:ここで言及されたリスクの簡単な説明から汚れた読み取りが間違っている場合を除き... 編集3:asを書き込むバックグラウンドチェックポイントの影響を考慮していないことに気付きましたディスクへのまだコミットされていないトランザクションので、はい、私の説明は誤解を招くものでした。
2番目のクエリでは、最初のバッチはコミットされていないデータを返すことができます(この場合は)。デフォルトのトランザクション分離レベルで実行される2番目のバッチREAD COMMITED
は、最初のセッションでコミットまたはロールバックが完了した後にのみ戻ります。
ここから、クエリプランと関連するロックレベルを確認できますが、SQL Serverのロックに関するすべてをここで読むことができます。
SELECT * FROM Table1
それがまさに私が必要とするものである場合、それはどのように悪い習慣ですか?