web-dev-qa-db-ja.com

ログファイルの圧縮後、レプリケーションとミラーリングのあるデータベースがLOG_BACKUPでスタックする

SQL Serverの専門家からのアドバイスが必要です。私はDBAではなく単なる開発者なので、私の無知を許してください。

私の環境は、SQL Server 2008 R2 x64(10.50.4339.0)の2つの等しいインスタンス(Node1とNode2)で構成されています。私は2つのデータベースを持っています:DB1とDB2、Full復旧モデル。両方のデータベースは、単一のSQLインスタンス内の相互間のレプリケーションに参加し、両方ともNode1からNode2にミラーリングされます。これらは本番データベースではなく、変更を行う前に完全なDBバックアップを作成しました。

ただし、問題が発生しました。プリンシパルのDB1とDB2の両方でログファイルが大きくならず、次のように実行されます。

select log_reuse_wait_desc, name, * from sys.databases where name='DB1' or name='DB2'

は、ログバックアップを手動で実行したにもかかわらず、DB1とDB2の両方に `log_reuse_wait_desc = 'LOG_BACKUP'があることを示しています。

これが、現在の状態を引き起こした一連のイベントです:

  1. 多くの構造およびデータ変更スクリプトの実行を伴う、年間の変更のセットでDB1およびDB2を更新する必要がありました。一部のデータスクリプトは非常に重く、テーブルが切り捨てられ、70K以上のINSERT呼び出しが含まれていました。それで、プリンシパル(Node1)で少しずつチャンクで変更を適用し始めました。
  2. Node1には、DB1およびDB2のデータとログファイルを含むパーティションで利用可能なディスク容量がすでに制限されていました。
  3. 変更を数回適用すると、log file full...メッセージが表示されます。そこで、DB1とDB2の両方のログファイルを停止して0Mbに縮小し、データ/構造の更新タスクを完了するためにディスク領域を解放しました。
  4. 両方のDBのログファイルが最小許容量に縮小されましたが、データの変更を続行した後、次のメッセージが表示されました。

メッセージ9002、レベル17、状態2、行1データベース 'DB2'のトランザクションログがいっぱいです。ログの領域を再利用できない理由を確認するには、sys.databasesのlog_reuse_wait_desc列を参照してください

データ/構造変更スクリプトの実行中に、関連するパーティションの空きディスク領域が数KBに減少し、SQL Serverから警告メールが送信されました。

log_reuse_wait_desc列を表示してNOTHINGを表示する方法を調査しました。ただし、提案された解決策では、DB1とDB2をシンプルリカバリモードにするか、それらをデタッチ/再アタッチする必要がありました。これは、レプリケーションとミラーリングのために実行できないことです。

Paul S. Randal からのアドバイスにも従い、ログバックアップを手動で実行しました。

 BACKUP LOG DB2 TO DISK = 'z:\DB2.TRN'

これは正常に完了しましたが、log_reuse_wait_descには引き続きLOG_BACKUPが表示され、ログファイルは増加していません。

DBCC LOGINFO出力:

DB1:次のような421レコード:

dbcc loginfo for DB1

DB2:次のような381レコード:

dbcc loginfo for DB2

DB2の初期loginfoレコード: https://i.stack.imgur.com/TTsVu.png

DB1のField列には値2と4が含まれているが、DB2のField列には値2のみが含まれていることに注意してください。ファイルサイズとオフセットフィールドは恐ろしく見えます:54GB +?空き容量が少ないかもしれません。現在、ドライブには26GBの空き容量があり、減少していません。 SQL Serverがハングしたようです。

レプリケーション/ミラーリングを無効にせずにバックアップから復元することなく、現在のDB1およびDB2を修正する方法はありますか?

どんな助けでも大歓迎です。

3
andrews

操作によってトランザクションログにギャップが生じ、仮想ログファイルが物理ログファイルの前にループバックするのを妨げているのではないでしょうか。概念的には、これは物理ファイルの終わりに達したときにすべきデータベース内で発生 です:

enter image description here

DBCC LOGINFOは、物理ログファイルの先頭のVLFのステータスが2であることを示すレコードを返します。これらのVLFはクリアする必要があります。これは、完全復旧モードでは、TLogバックアップをとる必要があることを意味します。この状況はlog_reuse_wait_desc表示する列LOG BACKUP 同じように。これを修正するには、論理ヘッダーを物理ファイルの先頭に向かって強制的に戻し、これらのステータス2 VLFをクリアする必要があります(そして、うまくいけばlog_reuse_wait_desc列はNOTHINGの表示に戻ります)。これを行うには、次の手順を実行します(DB1データベースとDB2データベースの両方で実行する必要がある場合があります)。

  1. ログバックアップ を実行します(例:BACKUP LOG [DBNAME]...)データベースに対して
  2. ターゲットサイズとして1 MBを指定して、トランザクションログファイルに対して DBCC SHRINKFILE 操作を実行します。
  3. データベースに対して別の Log Backup を実行します
  4. ターゲットサイズとして1 MBを指定して、トランザクションログファイルに対して別の DBCC SHRINKFILE 操作を実行します。
  5. ログファイルのサイズを手動で増やす 、段階的に Kimberly Trippの記事による を使用して、TLogを適切なサイズに戻します。

ここで何が起こっているのですか?

  1. 最初のログバックアップは、ディスクにフラッシュされた完了したトランザクションのバックアップを生成し、 非アクティブな仮想ログファイルを論理トランザクションログから削除 して、論理ログヘッダーまで再利用できるようにスペースを解放します。
  2. 最初のDBCC Shrinkfile操作 物理TLOGを現在の論理ログヘッダーが配置されている場所に縮小 し、可能な限り多くの領域を解放します。
  3. 2番目のログバックアップ操作は、論理ログ内をループバックし、論理ログヘッダーの前にある残りの非アクティブVLFをバックアップ/クリアできるようになりました。これらはおそらく何らかの理由で過去にフラッシュされたことはありませんが、この時点でクリアする必要があります。この手順は問題の修正に不可欠であり、ディスクに書き込む必要があるデータの量によっては、このバックアップに少し時間がかかる場合があります。
  4. 2番目のDBCC SHRINKFILE操作は、論理ログヘッダーを物理ログファイルの前に移動し、現在存在する可能性のある過剰なVLFを排除し、TLOGファイルを非常に小さなサイズ(この場合は1MB)に戻します。手順5でファイルを手動で拡張することは、VLF問題が再び発生しないようにするために不可欠です。
  5. Tlogのサイズを手動で増やすと、物理ログファイル内のVLFのサイズと数を制御できます。これは、これを適切に構成する絶好の機会なので、活用してください。

プロセスに関する最後のメモ。 tlogが非常にアクティブな場合は、これを数回、またはアクティビティが少ない時間帯に実行する必要がある場合があります。アクティビティが多いと、2番目のログバックアップを実行する前に、別の誤った自動拡張イベントが発生する可能性があります。これにより、基本的にはステップ3と考えていたものがステップ1に戻ります。通常、ステップ1と2はすぐに実行され、ステップ3の完了には最も時間がかかります。手順4と5を必ず実行してください。

2
John Eisbrener

あなたの状況は正常なものであり、あなたはそれを「修正」するために何もすべきではありません。

これがPaul Randaleの記事です log_reuse_wait_descがログバックアップの実行後にLOG_BACKUPと言うのはなぜですか?

これを理解するための重要な瞬間:

成長していないトランザクションログがあり、定期的なログバックアップを行っているが、log_reuse_wait_descはLOG_BACKUPのままである場合これは、前のログバックアップが実行されたときにVLFがゼロにクリアされたためです

それはどうして起こりますか?

挿入/更新/削除/ DDLアクティビティがほとんどないデータベースを想像してください。通常のログバックアップの間に生成されるログレコードはほんのわずかで、それらはすべて同じVLFにあります。次のログバックアップが実行され、これらのいくつかのログレコードがバックアップされますが、現在のVLFをクリアできないため、log_reuse_wait_descをクリアできません。データベースに十分な変更があり、現在のVLFがいっぱいになり、次のVLFがアクティブになると、次のログバックアップがクリアできるはずです。以前のVLFの場合、log_reuse_wait_descはNOTHINGに戻ります。次のログバックアップが発生し、現在のVLFをクリアできない場合、その場合は再度LOG_BACKUPに戻ります。

[LOG_BACKUPは、「ログのバックアップを取る必要があるか、バックアップされたログレコードがすべて現在のVLFにあるため、消去できなかったためです。」

あなたの状況と写真に戻ります。

最初のデータベースでは表示されませんが、2番目では正しい行が表示されました。そのログには381のVLFがあり、そのうちの1つだけがログのアクティブな部分を含んでいます。 VLFは57Mbです。

したがって、ログバックアップを実行したときに、バックアップするログ行は57Mb未満でした。すべての行は最後からのものでしたVLF(FSeqNo = 97737)、0 VLFがクリアされました。

しかし、これは問題ではありません。次のVLF=に到達し、ログバックアップを実行したら、log_reuse_wait_desc 変更されます。

1
sepupic

SQL Serverログファイルは、トランザクションを実行するために実行されたすべての手順の記録を作成します。トランザクションがロールバックされた場合、これらの手順を逆にする必要があります。

SIMPLE復旧モデルでは、トランザクションがコミットされると、ログの一部とその手順が解放され、再利用できます。

FULL復旧モデルでは、トランザクションログバックアップが実行されるまで、トランザクション情報がログに保持されます。データベースのすべての変更の手順をバックアップすることにより、トランザクションログのバックアップを(完全バックアップと組み合わせて)使用して、データベースを特定の時点に復元できます。

同じコマンドが他のサーバーに送信され、そこで同じ変更が行われるため、レプリケーションによってデータがログファイルに保持されることもあります。

新しいトランザクションが発生していても、ログファイルが他のトランザクションでいっぱいになっている場合、ログファイルが自動的に大きくなるように設定されていると(通常はデフォルトである)、データベースサーバーはログファイルを大きくしようとします。

ログファイルは自動的に縮小することもできます。ただし、これはnotがデフォルト設定です。なぜなら….

通常の操作条件下では、ログファイルを圧縮したくないです。通常のワークロードに対応するために、現在のサイズに成長しました。縮小すると、ほぼ確実に再び成長する必要があります。

これで、ログを再利用できない理由として_'LOG_BACKUP'_が表示されます。トランザクションログを手動で取得することに問題はありません。ただし、それがログがいっぱいであるという通常の理由である場合は、スケジュールされたジョブ(理想的には共有ファイルサーバー)を使用して、ログのバックアップを定期的に作成する必要があります。データベースがアクティブな場合、手動のログバックアップを実行した直後に新しいログアクティビティが発生します。最後のログバックアップ以降にCHECKPOINTがあった場合、_LOG_BACKUP_が表示されることがあります(ただし、ログがいっぱいではありません)。

大きなINSERTsが原因でログがいっぱいになる場合は、それらを小さなチャンクに分割し、各INSERTコマンドの間にログファイルのバックアップジョブが実行されることを確認してください。

注:コマンドDBCC SQLPERF (LOGSPACE);を使用して、ログファイルがどの程度いっぱいであるかを確認できます。これにより、ログファイルのサイズと、使用中のその領域の割合の両方が表示されます。

0
RDFozz