web-dev-qa-db-ja.com

コミットされていないトランザクション分離レベルを設定して更新ステートメントを読み取る

_set transaction isolation level read uncommitted_を含むストアドプロシージャがある場合、更新ステートメントに影響しますか?

更新/削除ステートメントでwith (nolock)を使用しないでください。これはほとんど同じことですが、SQLがプロシージャの更新ステートメントで無視するかどうか、または使用しないように注意する必要があるかどうかはわかりません更新ステートメントがある場合。

編集:

混乱させて申し訳ありません。このタイプのロックを操作ステートメントで使用した場合の効果や、それが良いアイデアかどうかを理解しようとはしていません。実際、私は操作ステートメントでこの種のロックを使用したくないので、私の質問は、 "set transaction ..."をストアドプロシージャの先頭に置くことが、更新/削除ステートメントによって常に受け入れられるかどうか、または無視されます。私の望みはそれが単に無視されることです。

私はそれがselect文に及ぼす影響(長所と短所)を十分に認識しています。

7
BVernon

「トランザクション分離レベル」は、主に(私の理解では)読み取り操作の動作、つまり読み取り操作がいくつかのロックを発行するかどうかに影響します。 「コミットされていない読み取り」の場合、これは [〜#〜] msdn [〜#〜] からの引用です

READ UNCOMMITTEDレベルで実行されているトランザクションは、他のトランザクションが現在のトランザクションによって読み取られたデータを変更できないようにする共有ロックを発行しません。 READ UNCOMMITTEDトランザクションは、現在のトランザクションが変更されたが他のトランザクションによってコミットされていない行を読み取ることを妨げる排他ロックによってもブロックされません。

したがって、あなたの質問に対する答えはNOです。更新は、同じストアドプロシージャ内の「コミットされていない読み取り」トランザクション分離レベルの影響を受けません。

-更新(このロジックを証明するサンプル)SSMSで2つのウィンドウを開き、ウィンドウ1(以下W1)で次を実行します

use tempdb
create table dbo.t (a int)
go
insert into dbo.t (a) values (10)
go
begin tran
update dbo.t 
set a = 20
where a = 10

-- commit tran

別のウィンドウ(W2)で、次を実行します(動作のコメントを参照)

use TempdB
set transaction isolation level read uncommitted
select * from dbo.t -- you can have dirty read, showing [a]=20, which is an uncommitted UPDATE in W1

go
-- the following update will wait (before proper locks are granted)
update dbo.t 
set a = 30
where a= 10

つまり、W2のUPDATEステートメント(READ UNCOMMITTEDあり)は、SELECTステートメントとしてのトランザクション分離レベル(つまり、期待どおりに動作)の影響を受けません。

-更新2:MSDNによる [〜#〜] update [〜#〜] t-sql、

WITH(Table_Hint_Limited)

ターゲットテーブルに許可される1つ以上のテーブルヒントを指定します。 WITHキーワードと括弧は必須です。 NOLOCKおよびREADUNCOMMITTEDは使用できません。テーブルヒントの詳細については、「テーブルヒント(Transact-SQL)」を参照してください。

したがって、SQLサーバーでUPDATEステートメントを実行すると、セッションでダーティデータを読み取ることができたとしても、ダーティデータ(つまり、コミットされていないデータ)を更新する方法はないと私は理解しています。

3
jyao

トランザクション分離レベルがコミットされていない状態で読み込まれたストアドプロシージャがある場合、更新ステートメントに影響しますか?

コミットされていない読み取りでは、ダーティリードが許可されます。ダーティになる前に、(データページまたはインデックス内の)行以上のレベルでXロックが取得されます。更新する行を検索するときにクエリによって直接アクセスされる行は、Uロックを取得してブロックされます。

ただし、更新が分離レベルの影響を受ける可能性があります。

接続1

CREATE TABLE T1
(
X INT NULL,
Y INT NULL
);

INSERT INTO T1 DEFAULT VALUES;

BEGIN TRAN
UPDATE T1 SET X = 100;    

WAITFOR DELAY '00:00:10'

ROLLBACK;

接続2(接続1の起動後10秒以内に実行します)

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

UPDATE T1
SET    Y = (SELECT SUM(X)
            FROM   T1);

SELECT *
FROM   T1; 

結果

enter image description here

読み取り操作でコミットされていない値が読み取られ、UPDATEで最終結果が使用されましたが、100読み取られたものは最終的にロールバックされました。

5
Martin Smith

編集に基づいて、質問がより明確になりました。

したがって、私の質問は、 "set transaction ..."をストアドプロシージャの先頭に置くことが、更新/削除ステートメントによって受け入れられるのか、それとも無視されるのかということです。

トランザクション分離レベルは、読み取り操作の観点から考える必要があります。分離レベルは、読み取り操作を他の書き込み操作から保護する方法を制御します。

データベースエンジンはすべての書き込み操作のロック動作を制御します。その動作をデータベースレベルで変更することはできません。

From [〜#〜] bol [〜#〜]

すべての分離レベルは、書き込み操作に対して常に排他ロックを発行し、トランザクションの期間全体にわたってロックを保持します。

読み上げる:

3
Kin Shah