ネットワークを切断するとクエリが停止しますか?


13

最近、100,000レコードに対して更新クエリを実行しました。クエリの実行中にミスを犯し、ネットワークケーブルをすぐに抜いたことに気付きました。

更新クエリ

  1. 処理を停止して完全にロールバックしますか?
  2. 処理を完了してコミットしますか?
  3. 処理を停止し、ターゲット行の一部のみを更新したままにしますか?

2
クエリがサーバーにヒットすると、サーバーでクエリをキャンセルしない限り続行されます。
JP Chauhan


1
マーティンのコメントは、あなたの質問に対する直接的な答え、ロボコップを提供します。クエリの実行が完了する前にネットワークがSQL Serverに切断を通知すると、SQL Serverはそれをロールバックします。それ以外の場合、SQL Serverにネットワークの切断が通知される前にクエリが完了すると、コミットされます。SQL Serverが部分的な更新を実行することはありません(単一の更新クエリを記述したと仮定)。
ニックチャマス

回答:


22

NickとMartinが述べたように、クエリの最終的なステータスは、クエリが完了する前にSQL Serverがネットワークケーブルのプルについて知っているかどうかによって異なります。以下からのオンラインブック(私はそれがこのために同等のトピックがであることは興味深い見つけるのに200020052008、および2008 R2ではなく、2012または2014):

エラーが原因でトランザクションを正常に完了できない場合、SQL Serverはトランザクションを自動的にロールバックし、トランザクションによって保持されているすべてのリソースを解放します。データベースエンジンのインスタンスへのクライアントのネットワーク接続が切断された場合、ネットワークが切断のインスタンスを通知すると、接続の未処理のトランザクションはすべてロールバックされます。クライアントアプリケーションに障害が発生した場合、またはクライアントコンピューターがダウンまたは再起動した場合も、これにより接続が切断され、ネットワークから切断が通知されると、データベースエンジンのインスタンスが未処理の接続をロールバックします。クライアントがアプリケーションからログオフすると、未処理のトランザクションはすべてロールバックされます。

(余談ですが、最後の2番目の文の接続というのは、おそらくトランザクションを意味していました。接続をどのようにロールバックするかはわかりません。)

同様に、SQL Serverは、サーバーが予期せずシャットダウンされた後、回復中にトランザクションを元に戻したりやり直したりすることがあります。これは、シャットダウン時のトランザクションの状態に依存します。私は人々があなたがやろうとしていたことを達成するためにこの戦術を使用することを見てきました(トランザクションをキャンセルします)、サーバーが再び起動したとき、作業の多くは単純にやり直されました予想よりもゼロまで)。

そのため、ネットワークケーブルを引っ張ったり、マシンの電源を切ったりするなど、パニックで抜本的なことをする代わりに、重要なシステムに対してアドホッククエリを実行することについて、より良い規律を持つことをお勧めします。たとえば、次の代わりに:

UPDATE dbo.sometable 
-- where *oops* I forgot this part

これを持っています:

BEGIN TRANSACTION;

UPDATE dbo.sometable
-- where *oops* I forgot this part

-- COMMIT TRANSACTION;
-- ROLLBACK TRANSACTION;

その後、更新が実際に正しい場合は、COMMITパーツを強調表示して実行できます。そうでない場合は、落ち着いROLLBACKパーツを強調表示して実行できます。SSMS Tools Packなどのアドインを使用してNew Queryテンプレートを編集し、その定型文を含めることもできます。

トランザクションが他のユーザーをブロックしているため、クエリを実行してからコミットまたはロールバックしない場合でも、問題が発生する可能性があります。しかし、これは取り返しのつかないほどデータを変更するよりはましです。

そしてもちろん、いつものように、信頼できるバックアップを用意してください。


5
これは優れたアドバイスであり、OPの問題の根本に対処しますが、クエリが引き続き実行されているかどうかの質問には実際には答えません。
ニックチャマス

3
@Nickに感謝します。私の動機は、症状ではなく原因(問題を引き起こした)に取り組むことでしたが、答えを更新しました。
アーロンバートランド

8

@Aaronは正しいです。コマンドの前にトランザクションを作成するのが最善の策です。それをするのを忘れることができないなら、1つのオプションはTools-Options設定に入って、つけることSET IMPLICIT_TRANSACTIONSです。これにより、特定のコマンドが実行されるとすぐにトランザクションが自動的に開始されます。これにUPDATEDELETEなどが含まれます。これは、何らかのコマンドのかなり完全なリストのよう"change"です。 SELECTリストにも含まれておりwill、トランザクションを開始します。トランザクションを開始するコマンドの完全なリストは、この設定で確認できます。トランザクションが既に開始されている場合、トランザクションは作成されません。これのマイナス面は、COMMIT変更を行った後に覚えておく必要があることです。

注:@Aaronの提案に基づいて、これを再度強調します。

This is very important!  You will have to remember to COMMIT after any change made!

基本的にはBEGIN、トランザクションを忘れて、何かをめちゃくちゃにしてしまいます。COMMITトランザクションを忘れて、それを開いたままにして、その日のままにしておくとハングします。トランザクションをロールバックすると考えてクエリウィンドウを閉じただけでテストしましたが、トランザクションをコミットまたはロールバックするかどうかを確認しました。

ここに画像の説明を入力してください


実際:トランザクションSELECT 開始します(投稿したリンクにも記載されています)
a_horse_with_no_name

@a_horse_with_no_nameを見つけてくれてありがとう!私は十分に注意深く読まなかったし、古い記憶から消えていた(明らかに間違っていた)。
ケネスフィッシャー

1
これは有用な投稿ですが、クエリが引き続き実行されているかどうかというOPの質問には実際には答えていません。
ニックチャマス

2
@Aaronの回答への追加として意図されていました。コメントを入れるのは大変でした。
ケネスフィッシャー

2

私は本当に依存すると思います:

ネットワークケーブルを抜く前にコマンドが既にサーバーに到達している場合、コマンドは引き続き正常に実行されます。

すべての更新コマンドをカプセル化するためのTransactionScope(他の言語ではない.Netで使用)がある場合、transactionScope.Complete()が実行されていないが保証されていない場合にのみ、トランザクションのコミットを停止できます。 。


2
「ネットワークケーブルを抜く前にコマンドが既にサーバーに到達している場合、コマンドは引き続き正常に実行されます。」これは、Martinが上記にリンクしたSQL Server BOLページと矛盾しています。「トランザクション処理中のエラー」を参照してください。
ニックチャマス

あなたが正しいです。トランザクションを指定すると、コマンドは自動的にロールバックされます。しかし、私たちが経験したように、トランザクションが明示的に指定されていない場合、アプリケーションを途中で停止してもコマンド(トランザクションのないバッチ更新)が完全に実行され、実際に接続が切断されました-しかし、タイミングとしては本当に良い例ではありませんおそらく正しくありませんでした。おそらくそれのためにいくつかのテストを行うのは良いことです
レックス
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.