1

スクリプト[1]で定義されたテーブルを持って、SSMSの2つのウィンドウでスクリプトを実行します

--1) first in first SSMS window
set transaction isolation level READ UNCOMMITTED;
begin transaction;
update aaa set Name ='bbb' 
    where id=1;
-- results in "(1 row(s) affected)"
--rollback

および1)後

--2)after launching 1)
select * from aaa --deleted comments
where id<>1
--is blocked

1)ウィンドウのトランザクション分離レベルとは関係なく、2)のSELECTはブロックされます。
なんで?

UPDATEの分離レベルは、他のトランザクションのステートメントに影響を与えますか?

最高の分離レベルは、2)のデフォルトのREADCOMMITTEDです。
範囲ロックは原因ではありません。SELECTはCOMMITTEDREADS(NONREPEATABLE READS)およびPHANTOM READS(Repeatable Reads)の問題に悩まされているはずです[2]
どうすればそれを苦しめることができますか?

SELECTをブロックせずにUPDATEを行うにはどうすればよいですか?

[1]

CREATE TABLE aaa
(
    Id int IDENTITY(1,1) NOT NULL,
    Name  varchar(13) NOT NULL
)


insert into  aaa(Name) 
   select '111' union all 
   select '222' union all 
   select '333' union all 
   select '444' union all 
   select '555' union all 
   select '666' union all 
   select '777' union all 
   select '888'  

[2] http://en.wikipedia.org/wiki/Isolation_(database_systems
) をクリックすると、コピーして貼り付けるか、末尾を追加します)

更新:
SELECT WITH(NOLOCK)はブロックされていません...

Update2:
または、同じことで、コミットされていない読み取り

UPDATEはSELECT行とは異なることに注意してください。
同じ場合でも、この動作は分離レベルの説明と矛盾します[2]

ポイントは次のとおりです。

  • 同じ(UPDATE-d)テーブルから他に誰がSELECTを実行するのかわからないが、行の更新とは無関係であると仮定します。
  • 分離レベルを理解する[2]

SQL Server 2008 R2 Dev

4

2 に答える 2

6

主キーがないためだと思います。これにより、ロックがエスカレートされ、SELECTがブロックされていると思います。ID 列に PRIMARY KEY を追加すると、再試行すると、SELECT が他の 3 行を返すことに気付くでしょう。WITH (NOLOCK) ヒントは必要ありません。

于 2010-10-24T21:58:23.453 に答える
2

後にテストを繰り返す

--3)
create index IX_aaa_ID on aaa(id)

SELECT 2) はまだブロックされています

--4)
drop index IX_aaa_ID on aaa
create unique index IX_aaa_ID on aaa(id)
--or adding primary key constraint   

SELECT 2) はブロックされていません

2)を次のように変更する場合

--2b)
select * from aaa 
    where id=3 
    --or as
    --WHERE id=2 

2b) は、インデックスまたは PK がなくてもブロックされないことを示しています。

ただし、2b) はインデックスなしで、1) UPDATE を修正した後にブロックされます。

--1c)  
set transaction isolation level serializable;
--set transaction isolation level REPEATABLE READ;

begin transaction;
update aaa set Name ='bbb' 
    where id=1;
--rollback

では、複数の行選択が共有不可能なロックを取得しようとしているように見えますか?

更新:
SELECT がブロックされている場合は常に、LCK_M_IS の取得を待機してい
ます。この料理を理解する十分な理由があります。

Update2:
テーブルでエスカレートされるのは UPDATE ロックではなく、SELECT (共有) ロック (SELECT が複数の行を読み取ろうとするとき) であり、テーブル ロックにエスカレートされ、テーブルが既に排他的 (UPDATE) になっているため付与できません。ロック。

そして、インデックスの有無は私の主な質問とは関係ありませんでした

このトピックの議論を、提出された提案「テーブルに既に排他ロックが含まれている場合、意図的な行ロックをテーブル ロックにエスカレートしてはならない」に移します。

于 2010-10-25T02:25:58.560 に答える