ROLLBACKは高速操作ですか?


回答:


14

SQL Serverの場合、コミット操作はLOP_COMMIT_XACTをログファイルに書き込んでロックを解除するだけであり、BEGIN TRAN以降にトランザクションが実行したすべてのアクションのROLLBACKよりも高速になることを主張できます。

コミットだけでなく、トランザクションのすべてのアクションを検討している場合、あなたのステートメントは真実ではないと主張します。外部要因、たとえばデータディスクの速度と比較したログディスクの速度を除くと、トランザクションによって行われた作業のロールバックは、そもそも作業を行うよりも速くなる可能性があります。

ロールバックとは、変更の順次ファイルを読み取り、それらをメモリ内のデータページに適用することです。元の「作業」では、実行計画の生成、ページの取得、行の結合などが必要でした。

編集:それはビットに依存します...

@JackDouglasは、ロールバックが元の操作よりも大幅に長くなる可能性がある状況の1つを説明するこの記事を指摘しました。この例は、必然的に並列処理を使用する14時間のトランザクションで、ロールバックはほとんどシングルスレッドであるため、ロールバックに48時間以上かかります。また、バッファプールを繰り返しかき回している可能性が高いため、メモリ内ページへの変更を元に戻すことはできません。

だから、私の以前の答えの改訂版。ロールバックはどれくらい遅くなりますか?他のすべてが考慮されますが、典型的なOLTPトランザクションではそうではありません。典型的な範囲外では、「行う」よりも「元に戻す」のに時間がかかることがありますが、(これは潜在的な言い回しですか?)なぜ「行う」が行われたかに依存します。

Edit2:コメントでの議論に続いて、ここで行われている作業が操作としてのコミットとロールバックの相対的な費用を決定する主要な要因であることを示す非常に不自然な例です。

2つのテーブルを作成し、非効率的にパックします(ページごとの無駄なスペース):

SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
SET NOCOUNT ON;
GO

CREATE TABLE dbo.Foo
(
    col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)

CREATE TABLE dbo.Bar
(
    col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
    , col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
GO

INSERT dbo.Foo DEFAULT VALUES
GO 100000

INSERT dbo.Bar DEFAULT VALUES
GO 100000

「悪い」更新クエリを実行し、作業にかかる時間とコミットの発行にかかる時間を測定します。

DECLARE 
    @StartTime DATETIME2
    , @Rows INT

SET @Rows = 1

CHECKPOINT
DBCC DROPCLEANBUFFERS

BEGIN TRANSACTION

SET @StartTime = SYSDATETIME()

UPDATE
    dbo.bar
SET
    col2 = REPLICATE('B', 4000)
FROM
    dbo.bar b
INNER JOIN
    (
    SELECT TOP(@Rows)
        col1
    FROM
        dbo.foo
    ORDER BY
        NEWID()
    ) f
ON  f.col1 = b.col1
OPTION (MAXDOP 1)

SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())

SET @StartTime = SYSDATETIME()

COMMIT TRANSACTION

SELECT 'Commit', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO

同じことを再度行いますが、ロールバックを発行して測定します。

    DECLARE 
    @StartTime DATETIME2
    , @Rows INT

SET @Rows = 1

CHECKPOINT
DBCC DROPCLEANBUFFERS

BEGIN TRANSACTION

SET @StartTime = SYSDATETIME()

UPDATE
    dbo.bar
SET
    col2 = REPLICATE('B', 4000)
FROM
    dbo.bar b
INNER JOIN
    (
    SELECT TOP(@Rows)
        col1
    FROM
        dbo.foo
    ORDER BY
        NEWID()
    ) f
ON  f.col1 = b.col1
OPTION (MAXDOP 1)

SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())

SET @StartTime = SYSDATETIME()

ROLLBACK TRANSACTION

SELECT 'Rollback', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO

@ Rows = 1の場合、かなり一貫した結果が得られます。

  • 検索/更新に5500ms
  • 3msコミット
  • 1msロールバック

@ Rows = 100の場合:

  • 8500msの検索/更新
  • 15ミリ秒のコミット
  • 15msロールバック

@ Rows = 1000の場合:

  • 15000msの検索/更新
  • 10msコミット
  • 500msロールバック

元の質問に戻ります。作業に加えてコミットにかかる時間を測定する場合、その作業の大部分は実際にデータを変更するのではなく、更新する行を見つけることに費やされるため、ロールバックが勝ちです。コミット操作を単独で見ている場合、コミットがそのような「作業」をほとんど行わないことは明らかです。コミットは「完了」です。


2
「少ない仕事」は必ずしも「速い」とは限らない
ジャックダグラス

begin tranトランザクションのカウンターが増えることは知っていました。私があなたを理解していれば、rdbmsはCOMMITですべてのタスクを実行しています(行を結合し、実行計画を生成します...)?
ガリック

3
いいえ、すべての作業はコミット前に行われます。コミット操作自体は比較的わずかです。
マークストーリースミス

@Mark 2m行を挿入し、コミットまたはロールバックする大まかな準備テストを行いました。ロールバックを含む全体の時間は10秒から30秒まで変化しましたが、コミットを含む全体の時間は6秒から14秒の間でした。YMMVはもちろんですが、これはボールパークロールバックが少なくとも私の環境では元のトランザクションとほぼ同じかそれより長いことを示しています。
ジャックダグラス

2
コミット操作が完了するまでの時間を測定する場合、チェックポイントが同時に発行されない限り(これは別個で無関係であるため)最小限であると思われます。それは私のポイントのようなものです、ロールバックはコミットの前に起こったすべてに加えてもう少しを行いますが、コミットはほとんどしません。テストのばらつきにより、他の要因が浮き彫りになりますが、後でいくつかのスクリプトを組み合わせてみます。
マークストーリースミス

13

Oracleの場合、ロールバックは、ロールバックする変更を行うのにかかった時間よりも何倍も長くかかる場合があります。多くの場合、これは重要ではありません。

  1. トランザクションがロールバックしている間、ロックは保持されません
  2. 低優先度のバックグラウンドプロセスによって処理されます

SQL Serverの場合、状況が同じかどうかはわかりませんが、そうでない場合は誰かが言うでしょう...

「なぜ」については、私が言うと思いますrollbackする必要があります珍しい何かがなくなって間違っていて、もちろん通常場合にのみ、commitはるかに一般的である可能性が高い-それはのために最適化するには理にかなっているように、commit


9

ロールバックは、「ああ、気にしない」だけではありません-多くの場合、それはすでに行ったことを取り消す必要があります。元のトランザクションが並行して実行された場合でも、ロールバックはシングルスレッドですが、ロールバック操作が常に元の操作よりも遅い、または常に速いというルールはありません。あなたが待っているなら、ただ待っておくのが最も安全だと思います。

もちろん、これはすべてSQL Server 2019でのすべての変更と、加速データベース回復(これも可変であるペナルティがありますが、データのサイズに関係なく瞬時にロールバックできます)。


2
そして、「ロールバックには時間がかかります。再起動しましょう」という会話がありました。
マークストーリースミス

多くのクライアントがそれを見ているのを見てきました。比較的無傷で出てくる人もいれば、それほど幸運ではない人もいます。
アーロンバートランド

1
@ MarkStorey-Smith-ロールバックの途中で再起動した場合、SQL Serverは起動時にロールバックを続行する必要はありませんか?
ニックChammas

2
依存する@Nick-たとえば、再起動前にロールバックがブロックされた場合、他のプロセスが強制終了されたため、サービスの再起動後、ロールバックがより速く動作する可能性があります。このシナリオには「what if」がたくさんあります。問題を「修正」するためにサーバーを再起動したり、サービスを再起動したりすると、おそらくもっと深刻な問題が発生します。
アーロンバートランド

2
@Nick、はい、まさにそれが起こります。私のコメントは「頬の舌」であることが意図されていたので、予期せず何かが動作しないときはいつでも再起動をしたいトリガーの幸せな人々にそれを説明しなければならないほどです。
マークストーリースミス

8

すべてのトランザクションのコミットアクティビティのパフォーマンスがロールバックよりも優れているわけではありません。そのようなケースの1つは、SQLの削除操作です。トランザクションが行を削除すると、これらの行はゴーストレコードとしてマークされます。コミットが発行され、ゴーストレコードのクリーンアップタスクが開始されると、これらのレコードのみが「削除」されます。

代わりにロールバックが発行された場合、これらのレコードからゴーストマーキングが削除されるだけで、集中的な挿入ステートメントは削除されません。


特定の操作がロールバック用に最適化される方法の良い例。
マークストーリースミス

5

すべてではありません。PostgreSQLは、ディスクI / Oの点で2つの操作が事実上同一であるため、コミットするよりもロールバックするのに時間がかかりません。私は実際に、これがコミットのために最適化されることの問題であるとは思いません。

基本的な質問は、ディスク上のレイアウトにどのように対処し、これがコミットとロールバックにどのように影響するかです。コミットよりもゆっくりとロールバックする主要なデータベースは、特にクラスター化されたテーブルからメインのデータ構造からデータを移動し、データの更新時にロールバックセグメントに入れる傾向があります。つまり、コミットするにはロールバックセグメントをドロップするだけですが、ロールバックするにはすべてのデータをコピーする必要があります。

PostgreSQLの場合、すべてのテーブルはヒープテーブルであり、インデックスは別個です。これは、ロールバックまたはコミットするときに、データを再配置する必要がないことを意味します。これにより、コミットとロールバックの両方が高速になります。

ただし、他のいくつかの処理が少し遅くなります。たとえば、プライマリキールックアップは、インデックスファイルをトラバースし、次にヒープテーブルにヒットする必要があります(適用可能なインデックスがカバーされていない場合)。これは大したことではありませんが、他の情報と可視性をチェックするために、余分なページ検索またはおそらくいくつかのランダムなページ検索(その行で多くの更新が発生した場合)を追加します。

ただし、ここでの速度は、PostgreSQLでの書き込み操作と読み取り操作の最適化の問題ではありません。一部の読み取り操作を他の読み取り操作よりも優先することは不本意です。その結果、PostgreSQLは他のデータベースと同様に平均して実行されます。より高速または低速になる可能性があるのは、特定の操作だけです。

だから、実際の答えは、データベースは読み取り側の特定のワークロード向けに最適化され、これが書き込み側の課題につながるということだと思います。通常、質問がある場合、コミットは常にではありませんが、通常はロールバックよりも優先されます。ただし、これはどちらかを行うことの意味に依存します(更新は削除とは異なります)。


良い答えですが、「PostgreSQLの場合、すべてのテーブルはヒープテーブルであり、インデックスは分離されています。これは、ロールバックまたはコミットするときにデータを再配置する必要がないことを意味します」むしろ、「コミットするよりもゆっくりとロールバックする主要なデータベースはデータを移動する傾向がある」ためであり、pgはあなたが述べたようにそうではないからです。Oracleはデフォルトでヒープストレージも使用します。主な違いは、Oracleは「バキューム」ルートではなく「取り消し」を使用し、コミット/ロールバックですべてのスペースを再利用することです。
ジャックダグラス14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.