7

たとえば、個人テーブルがあり、1行しかありません-

id = 1, name = 'foo'

1 つの接続で

select p1.id, p1.name, p2.name
from person p1 
join person p2 on p1.id = p2.id

同時に別の接続で:

update person set name = 'bar' where person.id = 1

Q1: update ステートメントのタイミングに基づいて、select が次のような結果を返すことは可能ですか?

id = 1, p1.name = 'foo', p2.name = 'bar'

どちらの接続も明示的なトランザクションを使用せず、どちらもデフォルトのトランザクション分離レベル READ COMMITTED を使用します。

問題は、SQLステートメントの開始時に取得されたロックがステートメントが完了するまで存在し続けるかどうか、またはステートメントがロックを解放して同じロックを再取得できるかどうかを理解するのに役立つことです行が同じステートメントで 2 回使用されている場合は?

Q2:set read_committed_snapshot onがデータベースに設定されている場合、質問への回答は変わりますか?

4

1 に答える 1

10

Q1: はい、少なくとも理論上は完全に可能です。read committedダーティデータを読み取らないことを保証するだけで、一貫性については約束しません。読み取りコミット レベルでは、データが読み取られるとすぐに共有ロックが解放されます (トランザクションの終了時でも、ステートメントの終了時でもありません)。

Q2: はい、この質問に対する答えは、read_committed_snapshotがオンになっていると変わります。これにより、ステートメント レベルの一貫性が保証されます。これを明確に述べているオンラインソースを見つけるのは難しいと思いますが、「Microsoft SQL Server 2008 Internals」のp.648から引用しています

RCSI のステートメントは、ステートメントの開始前にコミットされたすべてのものを認識します。トランザクション内の新しいステートメントごとに、コミットされた最新の変更が取得されます。

この MSDN ブログ投稿も参照してください。

セットアップ スクリプト

CREATE TABLE person 
(
id int primary key,
name varchar(50)
)

INSERT INTO person
values(1, 'foo');

接続 1

while 1=1
update person SET name = CASE WHEN name='foo' then 'bar' ELSE 'foo' END

接続 2

DECLARE @Results TABLE (
  id    int primary key,
  name1 varchar(50),
  name2 varchar(50))

while( NOT EXISTS(SELECT *
                  FROM   @Results) )
  BEGIN
      INSERT INTO @Results
      Select p1.id,
             p1.name,
             p2.name
      from   person p1
             INNER HASH join person p2
               on p1.id = p2.id
      WHERE  p1.name <> p2.name
  END

SELECT *
FROM   @Results  

結果

id          name1 name2
----------- ----- -----
1           bar   foo

mergeプロファイラーの他の結合タイプを見ると、この特定のクエリの結合または計画のいずれかの下でこの問題が発生する可能性はないように見えnested loopsます (すべてが取得されるまでロックは解放されread committedません)。一貫性については約束しません。実際には、SQL Server がデフォルトでこの結合タイプを選択しないため、投稿した正確なクエリに対してこの問題が発生しない可能性があります。ただし、必要な動作を生成するには、実装の詳細に依存する必要があります。

痕跡

S注意: 行レベルのロックが欠落しているように見える理由を知りたい場合は、ここで説明されている最適化について説明します

于 2011-01-23T12:13:32.650 に答える