0

2 つのセッションで 2 つのトランザクションが同じアイテムに対して実行されています:

セッション 1 では:

begin tran T1

   insert into Invoice with (item,OrderNumber) 

    select 'ItemA', max(OrderNumber)+1 

    from Orders

    where item='ItemA'

    waitfor delay '00:00:05'

commit T1

セッション 2 では:

begin tran T2

   insert into Invoice with (item,OrderNumber) 

    select 'ItemA', max(OrderNumber)+1 

    from Orders

    where item='ItemA'

commit T2

このようにすると、2 つの同一の行がテーブル Orders に挿入されます。しかし、どちらかのセッションでトランザクションを実行してから、別のトランザクションで新しい max(OrderNumber) を読み取り、次の値を挿入したいと考えています。次のように T1 にホールドロックを追加します。

begin tran T1

   insert into Invoice with (item,OrderNumber) 

    select 'ItemA', max(OrderNumber)+1 

    from Orders with (holdlock)

    where item='ItemA'

    waitfor delay '00:00:05'

commit T1

SQl SERVER は、select ステートメントを最初に解析してから、insert ステートメントに排他ロックを割り当てるため、最初に select に共有ロックを割り当てますか? 2 つのセッションでロックはどのように相互に機能しますか? ヒントをありがとう

4

3 に答える 3

1

トランザクションにシリアル化可能な分離レベルを使用できます。

元:

 set transaction isolation level serializable
 begin tran
    insert into Invoice with (item,OrderNumber) 
    select 'ItemA', max(OrderNumber)+1 
    from Orders
    where item='ItemA'

    waitfor delay '00:00:05'

 commit tran 

Serializable オプションは、次のトランザクション機能を提供します。

  1. ステートメントは、他のトランザクションによって変更されたがまだコミットされていないデータを読み取ることはできません
  2. 現在のトランザクションが完了するまで、他のトランザクションは現在のトランザクションによって読み取られたデータを変更できません
  3. 他のトランザクションは、現在のトランザクションが完了するまで、現在のトランザクションのステートメントによって読み取られるキーの範囲に入るキー値を持つ新しい行を挿入できません。

上記は問題に対して機能しますが、max ordernumber + 1 ロジックの代わりに ID 列を使用することをお勧めします。したがって、OrderNumber をテーブル内の ID に変更し、データを読み取るときに row_number 番号を使用して、実行時に Item ごとに注文番号を計算します。クエリの例を次に示します。

  select Item, Row_Number() over(partition by Item order by OrderNumber) as OrderNumber
  from Invoice

したがって、上記のクエリは必要な結果を提供します。

于 2013-08-06T20:26:50.957 に答える
0

データベース ロック スキームは、データベース管理アプリケーションの不可欠な部分です。データベースに格納されたデータの整合性のために、さまざまなデータベース ベンダーが提供するさまざまなロック スキームがあります。次のリンクを確認する必要があります最初のリンク

2 番目のリンク。それでも問題が解決しない場合はお知らせください。さらにサポートさせていただきます。

于 2013-08-06T20:27:53.750 に答える
0

あなたの究極の目標は何ですか。選択をロックして挿入を停止できないとは思いません。選択した行のみを更新からロックします。

于 2013-08-06T19:52:49.530 に答える