0

select が排他的トランザクションの一部であるときにどのように動作するかを理解できません。次のシナリオを検討してください –</p>

シナリオ 1 ステップ 1.1

create table Tmp(x int)
insert into Tmp values(1)

ステップ 1.2 – セッション 1

begin tran
set transaction isolation level serializable 
select * from Tmp

ステップ 1.3 – セッション 2

select * from Tmp

最初のセッションが終了していなくても、セッション 2 で tmp テーブルを読み取ることができます。Tmp には排他ロックがあり、セッション 2 でクエリを選択するために共有ロックを発行するべきではないと思っていましたが、それは起こっていません。デフォルトの分離レベルが READ COMMITED であることを確認しました。

この動作を理解するのを手伝ってくれてありがとう。

編集:排他ロックで選択する必要があるのはなぜですか?

実際に連続した値を生成する SP があります。だから流れは -

  1. テーブルから最大値を読み取り、値を変数に格納する
  2. 更新テーブル セット値=値+1

この SP は、数千のインスタンスによって並行して実行されます。2 つのインスタンスが同時に SP を実行すると、同じ値が読み取られ、値 +1 が更新されます。私は実行ごとに連続した値を持ちたいと思っていますが。選択が排他ロックの一部でもある場合にのみ可能だと思います。

4

1 に答える 1

0

トランザクションをシリアライズ可能にする場合は、最も外側のトランザクションを開始する前に、そのオプションを変更する必要があります。したがって、最初のセッションは正しくなく、実際にはコミットされた読み取り (またはそのセッションで有効だった他のレベル) で実行されています。

SELECTただし、ステートメントの順序を修正しても、プレーンステートメントの排他ロックは取得されません。


プレーンに排他ロックを取得させたい場合はSELECT、それを要求する必要があります。

select * from Tmp with (XLOCK)

または、実際に排他ロックを必要とするステートメントを実行する必要があります。

update Tmp set x = x

最初のセッションはデータを変更しないため、排他ロックは必要ありません。最初の (シリアル化可能な) セッションが完了まで実行され、2 番目のセッションが開始される前にロールバックまたはコミットされた場合、最初のセッションはデータを変更しなかったため、そのセッションの結果は同じになります。取引の性質は正しかった。

于 2014-08-08T06:37:43.653 に答える