はじめに
ごく最近、私の同僚が、キーアプリケーションテーブルにWHERE句を指定せずに更新ステートメントを発行したことに必死になって私に来ました。フロントエンドへの影響は悲惨なものになるため、メールやエスカレーションが入り始める前に、どうしても状況を逆転させるための支援が緊急に必要だったため、彼は直接私に来ました。
状況を調べたところ、変更がセカンダリデータベースに適用されていないことがわかりました。ほとんどの場合、プライマリデータベースとセカンダリデータベースの間の遅延は20分です(パフォーマンスの問題を回避するために少しずらしています)。エラーに気付いた直後に同僚が助けを求めたため、セカンダリデータベースからデータを回復することができました。このような遅延の価値については、この記事で説明しました。 。
シナリオレビュー
ただし、この構成の小さな欠点(IMPLICIT TRANSACTIONS =OFF)は、ユーザーがステートメントを再考して、Oracleで非常に一般的なROLLBACKを発行する機会がないことです。図1は、SQL ServerManagementStudioで使用できるANSIクエリオプションを示しています。
図。 1 SQL ServerManagementStudioのANSIデフォルト
暗黙のトランザクションの使用
本質的に、このデフォルト構成または最も望ましいクライアントツールで直面する問題は、SQLステートメントを実行するとロールバックできないことです。セッションで暗黙のトランザクションを有効にすることで、これを回避できます。これにより、必要に応じてトランザクションをロールバックする機会が得られます。図2と図4は、この設定を1つのセッションでのみオンにできることを示しています。ただし、これにより、ROLLBACKまたはCOMMITが発行されない場合にユーザーセッションが他のセッションをブロックするリスクを取り除くことはできません。
>
図。 1つのセッションでの2つの暗黙的なトランザクション
-- Listing 1: UPDATE Table TAB2 with IMPLICIT_TRANSACTIONS ON SET IMPLICIT_TRANSACTIONS ON DECLARE @IMPLICIT_TRANSACTIONS VARCHAR(3) = 'OFF'; IF ( (2 & @@OPTIONS) = 2 ) SET @IMPLICIT_TRANSACTIONS = 'ON'; SELECT @IMPLICIT_TRANSACTIONS AS IMPLICIT_TRANSACTIONS; USE KTrain GO SELECT * FROM Tab2; GO UPDATE TAB2 SET countryCode='SA' -- WHERE fname='Joyce'; GO SELECT * FROM Tab2; GO
図。 3すべての行が更新されました
ここで説明する回避策を説明するために、リスト1のSQLコードを見てみましょう。ジュニア開発者である通常のSQL Serverユーザーに、特定の条件下で実行する一連のスクリプトが与えられていると仮定します。 。スクリプトでは、WHERE句がコメント化されています。これは、このスクリプトを実行するたびに、述語を変更する必要があるためです。もちろん、これは単純な使用例であり、リスクにはさまざまな方法で対処できますが、ロールバックを実行する可能性を示したいだけです。
IMPLICIT TRANSACTIONを既にオンにしていることを思い出してください。したがって、このステートメントを実行すると、SQLServerはトランザクションをCOMMITまたはROLLBACKすることを期待します。開発者の意図は、JoyceAfamのcountryCodeを更新することです。 彼女は南アフリカに移住して以来、「SA」になりました。図3は、開発者がこれを実行しようとしているときに、値SAを countryCodeとして誤ってすべての行を更新したことを示しています。 。彼らはこれに気づき、ロールバックを発行します。
図。 4ロールバックの発行
図。別のセッションでの5つの暗黙のトランザクション
ただし、IMPLICIT TRANSACTIONSをオンにしていない他のセッションでは、開発者がエラーから回復できないことがわかりました。この場合、ロールバックを正常に発行することはできません。その場合、リカバリにはデータの復元が伴います。
図。 6暗黙のトランザクションがオンになっていないとロールバックは不可能です
明示的なトランザクションの使用
同じ効果を達成するための別のアプローチは、BEGIN TRANを明示的に指定することにより、DMLをトランザクションに含めることです。繰り返しになりますが、COMMITまたはROLLBACKのいずれかを使用して、トランザクションを完了することが非常に重要です。このディスカッションのコンテキストでは、コードにエラーがあることがわかったため、ROLLBACKを発行します。
-- Listing 2: UPDATE Table TAB2 with Explicit Transaction BEGIN TRAN GO USE KTrain GO SELECT * FROM Tab2; GO UPDATE TAB2 SET countryCode='GH' -- WHERE fname='Joyce'; GO SELECT * FROM Tab2; GO ROLLBACK; SELECT * FROM Tab2; GO - Listing 3: Corrected UPDATE Statement BEGIN TRAN GO USE KTrain GO SELECT * FROM Tab2; GO UPDATE TAB2 SET countryCode='SA' WHERE fname='Joyce'; GO SELECT * FROM Tab2; GO
結論
この記事では、ロールバックの機会を作成し、誤ったDMLに起因するユーザーエラーを軽減するための適切な回避策について簡単に触れました。また、このアプローチの主なリスクである、不注意によるブロッキングについても説明しました。 DBAは、 sys.dm_tran_session_transactions、sys.dm_tran_locks にクエリを実行することにより、このリスクが存在する可能性について調査を開始できます。 、および同様の動的管理オブジェクト。
参照
-
ログ配布と遅延リカバリを使用したデータ損失の修正
-
暗黙のトランザクションを設定
-
暗黙のトランザクションを悪い考えに設定する
-
トランザクションのDMV