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