web-dev-qa-db-ja.com

コミットされたスナップショットVSスナップショット分離レベルの読み取り

SQL ServerでREAD COMMITTED SNAPSHOTよりもSNAPSHOT分離レベルをいつ使用するかを理解してくれる人がいますか?

ほとんどの場合、READ COMMITTED SNAPSHOTが機能することを理解していますが、SNAPSHOT分離に進むタイミングはわかりません。

ありがとう

67
user173552

READ COMMITTED SNAPSHOTは、楽観的な読み取りと悲観的な書き込みを行います。対照的に、SNAPSHOTは楽観的読み取りと楽観的書き込みを行います。

マイクロソフトではREAD COMMITTED SNAPSHOT行のバージョン管理が必要なほとんどのアプリの場合。

この優れたMicrosoftの記事を読んでください: 行のバージョン管理ベースの分離レベルの選択 。両方の分離レベルの利点とコストについて説明します。

より詳細なものは次のとおりです。 http://msdn.Microsoft.com/en-us/library/ms345124(SQL.90).aspx

71
Bill Paetzke

enter image description here [![分離レベルテーブル] [2]] [2]

以下の例を参照してください。

コミットされたスナップショットの読み取り

以下のようにデータベースプロパティを変更します

ALTER DATABASE SQLAuthority
SET READ_COMMITTED_SNAPSHOT ON WITH ROLLBACK IMMEDIATE
GO

セッション1

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 4
WHERE i = 1

セッション2

USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 1

結果-セッション2のクエリは、現在のトランザクションがコミットされていないため、古い値(1、1)を表示します。これは、ブロックを回避し、コミットされたデータを読み取る方法です。

セッション1

COMMIT

セッション2

USE SQLAuthority
GO
SELECT *
FROM   DemoTable
WHERE i = 1

結果-セッション1で行が更新されるため、セッション2のクエリには行が表示されません。そのため、コミットされたデータが表示されます。

スナップショット分離レベル

これは新しい分離レベルであり、SQL Server 2005以降で使用できました。この機能では、新しい分離レベルを使用する必要があるため、アプリケーションに変更が必要です。

以下を使用してデータベース設定を変更します。データベースにトランザクションがないことを確認する必要があります。

ALTER DATABASE SQLAuthority SET AllOW_SNAPSHOT_ISOLATION ON

ここで、以下を使用して接続の分離レベルを変更する必要もあります

セッション1

USE SQLAuthority
GO
BEGIN TRAN
UPDATE DemoTable
SET i = 10
WHERE i = 2

セッション2

SET TRANSACTION ISOLATION LEVEL SNAPSHOT
GO
USE SQLAuthority
GO
BEGIN TRAN
SELECT *
FROM   DemoTable
WHERE i = 2

結果-値を10に変更しても、セッション2(2、2)には古いレコードが表示されます。

それでは、セッション1でトランザクションをコミットしましょう

セッション1

COMMIT

セッション2に戻って、もう一度selectを実行してみましょう。

セッション2

SELECT *
FROM   DemoTable
WHERE i = 2

セッション2がスナップショット分離を使用してトランザクションを指定したため、レコードは引き続き表示されます。トランザクションを完了しない限り、最新のレコードは表示されません。

セッション2

COMMIT
SELECT *
FROM   DemoTable
WHERE i = 2

これで、行は既に更新されているため表示されません。

参照: SQL AuthoritySafari Books Online

34
Akira Yamamoto

スナップショットとスナップショット読み取りコミットの比較は、スナップショットで発生する可能性があるが、スナップショット読み取りコミットではない恐ろしい「スナップショット更新の競合」例外の議論なしでは完全ではありません。

一言で言えば、スナップショットアイソレーションは、コミットされたデータのスナップショットをトランザクションの開始で取得し、読み取りと書き込みの両方に楽観的ロックを使用します。トランザクションをコミットしようとしたときに、他の何かが同じデータの一部を変更したことが判明した場合、データベースはトランザクション全体をロールバックし、呼び出し元コードでスナップショット更新競合例外を引き起こすエラーを発生させます。これは、トランザクションの影響を受けるデータのバージョンが、トランザクションの終了時と開始時と同じではないためです。

スナップショット読み取りコミットは、書き込みロック(悲観的書き込み)を使用し、すべてのコミット済みデータのスナップショットバージョン情報を各ステートメントの統計で取得するため、この問題の影響を受けません。

Snapshot Read Committedではなく、Snapshotでスナップショットの更新の競合が発生する可能性は、2つの間の非常に大きな違いです。

5
user3444696

ビルのコメントから始めて、関連性はありますが、私はもっと読み、他の誰かに役立つかもしれないメモを作りました。

デフォルトでは、単一ステートメント(「SELECT」を含む)は「コミット済み」データ(READ COMMITTED)で機能します。質問は、データが「アイドル」になるのを待って、読み取り時に他のユーザーの動作を停止するかです。

DBを右クリックして「プロパティ->オプション->その他」で設定:

同時実行性/ブロック:コミットスナップショットの読み取りがオン [デフォルトはオフ、オンにする必要があります]:

  • 選択(読み取り)にはSNAPSHOTを使用し、他のユーザーを待機したり、ブロックしたりしないでください。
  • コード変更なしのエフェクト操作
  • ALTER DATABASE SET READ_COMMITTED_SNAPSHOT [ON | OFF]
  • SELECT name、is_read_committed_snapshot_on FROM sys.databases

整合性:スナップショット分離を許可 [デフォルトはオフ、議論可能– OKオフ]:

  • クライアントがSQLステートメント(トランザクション)全体でSNAPSHOTを要求できるようにします。
  • コードは「トランザクション」スナップショットを要求する必要があります(SET TRANSACTION ...など)
  • ALTER DATABASE SET ALLOW_SNAPSHOT_ISOLATION [ON | OFF]
  • SELECT name、is_read_committed_snapshot_on FROM sys.databases

質問:コミットされたスナップショットの読み取りとスナップショットの分離の許可の間では、1つではありませんまたはです。これらはスナップショットの2つのケースであり、個別にオンまたはオフにすることができます。スナップショットの分離を許可するには、もう少し高度なトピックを使用します。 [スナップショットの分離を許可する]を使用すると、コードはスナップショットの土地をさらに制御することができます。

1行について考えると、問題は明確に見えます。デフォルトではシステムにコピーがないため、読者は他の誰かが書いている場合は待機し、作家は他の誰かが読んでいる場合も待機する必要があります。時間。 「Is Read Committed Snapshot On」を有効にすると、これらのロックを回避するために「スナップショットコピー」をサポートするようにDBがアクティブになります。

Rambling on ...

私の意見では、「コミットされたスナップショットを読み取ります」は、通常のMS SQLServerデータベースでは「TRUE」であり、デフォルトで「FALSE」で出荷されるのは時期尚早の最適化です。

ただし、テーブル全体で複数の行をアドレス指定する可能性があるためだけでなく、1つの行ロックが悪化するだけでなく、SQL Serverでは「ブロック」レベルのロック(ストレージの近接によって関連付けられたランダムな行のロック)を使用して行ロックが実装されるため、複数のロックがテーブルロックをトリガーするしきい値があります-おそらく、ビジー状態のデータベースで問題をブロックするリスクのある「より楽観的な」パフォーマンス最適化。

0
Cris Mooney