web-dev-qa-db-ja.com

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

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

クエリを更新しますか

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

NickとMartinが述べたように、クエリの最終的なステータスは、クエリが完了する前にSQL Serverがネットワークケーブルのプルを認識しているかどうかによって異なります。 Books Online から( 2020052008 にこれと同等のトピックがあることは興味深いと思いますが、および 2008 R2 、ただし2012または2014は除く):

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

(余談ですが、最後の2番目の文のWordconnectionsはおそらくtransactions。接続をロールバックする方法がわかりません。)

同様に、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部分をcalmly強調表示して実行できます。 SSMS Tools Pack のようなアドインを使用してNew Queryテンプレートを編集し、そのボイラープレートを含めることもできます。

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

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

22
Aaron Bertrand

@アーロンは正しいです。コマンドの前にトランザクションを作成するのが最善の策です。それを思い出せない場合は、Tools-Options設定に移動してSET IMPLICIT_TRANSACTIONSをオンにする方法があります。これにより、特定のコマンドが実行されるとすぐにトランザクションが自動的に開始されます。これにはUPDATEDELETEなどが含まれます。これは、"change"となるコマンドのかなり完全なリストのようです。 SELECTもリストに含まれ、willはトランザクションを開始します。トランザクションを開始するコマンドの完全なリストは、この設定 here で確認できます。トランザクションがすでに開始されている場合、トランザクションは作成されません。これの欠点は、変更を加えた後はCOMMITを覚えておく必要があることです。

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

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

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

enter image description here

8
Kenneth Fisher

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

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

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

2
Rex