18

SQLServerの分離/ロックを理解しようとしています。

READ COMMITTED分離レベルで次のシナリオがあります(デフォルト)

テーブルがあります。

create table Transactions(Tid int,amt int)

with some records

insert into Transactions values(1, 100)
insert into Transactions values(2, -50)
insert into Transactions values(3, 100)
insert into Transactions values(4, -100)
insert into Transactions values(5, 200)

今msdnから私は理解しました

選択が実行されると、共有ロックが取得されるため、他のトランザクションはデータを変更できません(ダーティリードを回避します)。ドキュメントでは、行レベル、ページレベル、テーブルレベルのロックについても説明しています。次のシナリオを考えました

Begin Transaction

select * from Transactions

/*
some buisness logic which takes 5 minutes

*/

Commit

私が理解したいのは、共有ロックが取得される期間と、それ(行、ページ、テーブル)です。

ロックは、ステートメントselect * from Transactionsが実行されたときにのみ取得されるか、COMMITに到達するまで5分以上取得されます。

4

4 に答える 4

24

あなたは間違った質問をしている、あなたは実装の詳細について心配している。考えて気にする必要があるのは、分離レベルのセマンティクスです。ケンドラリトルはそれらを説明する素敵なポスターを持っています:無料ポスター!SQLServer分離レベルのガイド

あなたの質問は次のように言い換える必要があります:

アイテムから*を選択

Q:どのアイテムが表示されますか?
A:すべてのコミットされたアイテム

Q:アイテムを挿入/削除/更新したコミットされていないトランザクションがある場合はどうなりますか?
A:SELECTは、コミットされていないすべてのアイテムがコミット(またはロールバック)されるまでブロックされます。

Q:上記のクエリの実行に新しいアイテムが挿入/削除/更新された場合はどうなりますか?
A:結果は未定です。いくつかの変更が表示される場合がありますが、他の変更は表示されず、一部がコミットされるまでブロックされる可能性があります。

READ COMMITTEDは、トランザクションの長さに関係なく、ステートメントが終了すると約束をしません。ステートメントを再度実行すると、以前の状態とまったく同じセマンティクスが再び得られ、以前に表示したアイテムが変更、非表示になり、新しいアイテムが表示される可能性があります。明らかに、これは、選択後にアイテムに変更を加えることができることを意味します。

分離レベルが高いほど、より強力な保証が得られます。REPEATABLEREADは、コミットするまで、最初に選択したアイテムを変更または削除できないことを保証します。SERIALIZABLEは、コミットする前に2番目の選択に新しいアイテムが表示されないという保証を追加します。

これはあなたが理解する必要があることであり、実装メカニズムがどのように機能するかではありません。これらの概念を習得した後、実装の詳細を尋ねることができます。これらはすべて、トランザクション処理:概念と手法で説明されています。

于 2012-07-04T14:23:45.087 に答える
20

あなたの質問は良いものです。取得されるロックの種類を理解することで、DBMSを深く理解できます。SQL Serverでは、すべての分離レベル(読み取り非コミット、読み取りコミット(デフォルト)、繰り返し可能読み取り、シリアル化可能)で、書き込み操作のために排他ロックが取得されます。

排他ロックは、分離レベルに関係なく、トランザクションが終了すると解放されます。

分離レベルの違いは、共有(読み取り)ロックの取得/解放方法を示しています。

Read Uncommitted分離レベルでは、共有ロックは取得されません。この分離レベルでは、「ダーティリード」(トランザクションは、実行中の別のトランザクションによって変更され、まだコミットされていない行からデータを読み取ることができるため、ロールバックされる可能性があります)と呼ばれる同時実行の問題が発生する可能性があります。

Read Committed分離レベルでは、関連するレコードの共有ロックが取得されます。共有ロックは、現在の命令が終了すると解放されます。この分離レベルは「ダーティリード」を防ぎますが、レコードは他の同時トランザクションによって更新される可能性があるため、「非反復可能リード」(トランザクションAは行を取得し、トランザクションBはその後行を更新し、トランザクションAは後で同じ行を再度取得します) 。トランザクションAは同じ行を2回取得しますが、異なるデータを参照します)または「ファントム読み取り」(トランザクションの過程で、2つの同一のクエリが実行され、2番目のクエリによって返される行のコレクションが最初のクエリとは異なります)が発生する可能性があります。

繰り返し可能読み取りの分離レベルでは、トランザクション期間中、共有ロックが取得されます。「ダーティリード」と「非反復可能リード」は防止されますが、「ファントムリード」は引き続き発生する可能性があります。

シリアル化可能な分離レベルでは、トランザクション期間中、遠隔共有ロックが取得されます。上記の同時実行の問題は発生しませんが、パフォーマンスが大幅に低下し、デッドロックが発生するリスクがあります。

于 2016-05-31T11:03:53.160 に答える
7

select * from Transactionロックは、が実行されたときにのみ取得されます

以下のコードで確認できます

SQLセッションを開き、このクエリを実行します

Begin Transaction

select * from Transactions

 WAITFOR DELAY '00:05'
/*
some buisness logic which takes 5 minutes

*/

Commit

別のSQLセッションを開き、以下のクエリを実行します

Begin Transaction
Update Transactions
Set = ...
where ....
commit
于 2012-07-04T11:56:59.797 に答える
0

まず、ロックはステートメントの実行時にのみ取得します。あなたの声明は2つの部分に分かれており、単純化すると仮定します。

select * from Transactions
update Transactions set amt = xxx where Tid = xxx

READ COMMITTED分離レベルでいつ/どのロックが保持/解放されますか?実行時 select * from Transactionsに、ロックは取得されません。

以下update Transactions set amt = xxx where Tid = xxxは、更新/更新されたキー用のXロック、ページ/タブ用のIXロックを追加します

すべてのロックは、コミット/ロールバック後にのみ解放されます。これは、トランス実行中にロックが解除されないことを意味します。

于 2018-08-17T10:51:26.967 に答える