sql >> データベース >  >> RDS >> Sqlserver

SQL Serverトランザクションログ、パート3:ログの基本

    このシリーズの第2部では、トランザクションログの構造階層について説明しました。この投稿は主に私が説明した仮想ログファイル(VLF)に関係しているため、続行する前に2番目の部分を読むことをお勧めします。

    すべてがうまくいくと、トランザクションログは際限なくループし、既存のVLFを再利用します。この動作は、私がログの循環的な性質と呼んでいるものです。 。ただし、場合によっては、これを防ぐために何かが発生し、トランザクションログがどんどん大きくなり、VLFがどんどん追加されます。この投稿では、これらすべてがどのように機能するか、または機能しない場合があるかについて説明します。

    VLFとログの切り捨て

    すべてのVLFには、VLFに関するメタデータを含むヘッダー構造があります。構造内で最も重要なフィールドの1つは、VLFのステータスであり、関心のある値はゼロです。つまり、VLFは非アクティブです。 、および2つは、VLFがアクティブであることを意味します。 。非アクティブなVLFは再利用できますが、アクティブなVLFは再利用できないため重要です。 VLFは完全にアクティブまたは完全に非アクティブであることに注意してください。

    VLFは、必要なログレコードが含まれている間はアクティブなままであるため、再利用したり上書きしたりすることはできません(次回はログレコード自体について説明します)。ログレコードが必要になる理由の例は次のとおりです。

    • ログレコードが含まれている長時間実行されるトランザクションがあるため、トランザクションがコミットされるか、ロールバックが完了するまで、ログレコードを解放できません。
    • ログバックアップはまだそれらのログレコードをバックアップしていません
    • ログのその部分は、トランザクションレプリケーションまたは変更データキャプチャのためにログリーダーエージェントによってまだ処理されていません
    • ログのその部分は、非同期データベースミラーまたは可用性グループのレプリカにまだ送信されていません

    VLFがアクティブのままである理由がない場合、ログの切り捨てと呼ばれるプロセスが実行されるまで、VLFが再び非アクティブに切り替わらないことに注意することが重要です。 発生します–これについては以下で詳しく説明します。

    5つのVLFと1から始まるVLFシーケンス番号のみを含む単純な架空のトランザクションログを使用すると(前回から実際にはそうならないことを覚えておいてください)、トランザクションログが作成されると、VFL1はすぐにアクティブとしてマークされます。トランザクションログ内の少なくとも1つのアクティブなVLF(ログブロックが現在書き込まれているVLF)である必要があります。シナリオの例を以下の図1に示します。

    図1:5つのVLF、シーケンス番号1を含む架空の新しいトランザクションログ5まで。

    より多くのログレコードが作成され、より多くのログブロックがトランザクションログに書き込まれると、VLF 1がいっぱいになるため、下の図2に示すように、より多くのログブロックを書き込むには、VLF2をアクティブにする必要があります。

    図2:アクティビティはトランザクションログを移動します。

    SQL Serverは、最も古いコミットされていない(アクティブな)トランザクションの開始を追跡し、このLSNは、チェックポイント操作が発生するたびにディスク上に保持されます。トランザクションログに書き込まれた最新のログレコードのLSNも追跡されますが、さまざまな競合状態に遭遇することなくディスクを永続化する方法がないため、メモリ内でのみ追跡されます。クラッシュリカバリ中にのみ使用されるため、これは問題ではありません。SQLServerは、クラッシュリカバリ中にトランザクションログの「終了」のLSNを計算できます。チェックポイントとクラッシュリカバリは、シリーズの今後の投稿のトピックです。

    最終的に、VLF 2がいっぱいになり、VLF3がアクティブになります。トランザクションログの循環的な性質の要点は、トランザクションログ内の以前のVLFが非アクティブになり、再利用できるようになることです。これは、ログの切り捨てと呼ばれるプロセスによって実行されます。 、これは一般にログクリアリングとも呼ばれます 。残念ながら、実際には何も切り捨てられたりクリアされたりしないため、これらの用語はどちらもひどい誤称です。

    ログの切り捨ては、トランザクションログ内のすべてのVLFを調べて、どのアクティブなVLFを再度非アクティブとしてマークできるかを判断するプロセスです。これは、SQLServerではそれらのコンテンツがまだ必要ないためです。ログの切り捨てが実行される場合、アクティブなVLFを非アクティブにできる保証はありません。これは、データベースで何が起こっているかに完全に依存します。

    ログの切り捨てについては、よくある誤解が2つあります。

    1. トランザクションログが小さくなります(「切り捨て」の誤解)。いいえ、そうではありません。ログの切り捨てによるサイズの変更はありません。トランザクションログを小さくできるのは、明示的なDBCCSHRINKFILEだけです。
    2. 非アクティブなVLFは、何らかの方法でゼロにされます(「クリア」誤解)。いいえ– VLFヘッダーのいくつかのフィールドを除いて、非アクティブにされた場合、VLFには何も書き込まれません。

    以下の図3は、VLF 3と4がアクティブであり、ログの切り捨てによってVLF1と2が非アクティブであることを示すことができたトランザクションログを示しています。

    図3:ログの切り捨てにより、以前のVLFが非アクティブとしてマークされます。

    ログの切り捨てが発生するタイミングは、データベースで使用されているリカバリモデルによって異なります。

    • 単純なモデル:チェックポイント操作が完了すると、ログの切り捨てが発生します
    • 完全モデルまたは一括ログモデル:ログの切り捨ては、ログのバックアップが完了すると発生します(同時の完全バックアップまたは差分バックアップが実行されていない場合、データのバックアップが完了するまでログの切り捨ては延期されます)

    これには例外はありません。

    ログの円形の性質

    トランザクションログを大きくする必要がないようにするには、ログの切り捨てでVLFを非アクティブとしてマークできる必要があります。トランザクションログが循環的な性質を持つためには、ログの最初の物理VLFが非アクティブである必要があります。

    以下の図4を検討してください。これは、VLF 4および5が使用中であり、ログの切り捨てによってVLF1から3が非アクティブとしてマークされていることを示しています。より多くのログレコードが生成され、より多くのログブロックがVLF 5に書き込まれ、最終的にはいっぱいになります。

    図4:アクティビティはトランザクションログの最も高い物理VLFを埋めます。

    この時点で、データベースのログマネージャーは、トランザクションログの最初の物理VLF(この例ではシーケンス番号1のVLF 1)のステータスを確認します。VLF1は非アクティブであるため、トランザクションログはラップアラウンドできます。最初から再び充填を開始します。ログマネージャは、最初のVLFをアクティブに変更し、そのシーケンス番号を現在の最大のVLFシーケンス番号より1つ大きくします。したがって、それはVLF 6になり、ログはそのVLFに書き込まれるログブロックで続行されます。これは、以下の図5に示すように、ログの循環的な性質です。

    図5:トランザクションログとVLFの再利用の循環的な性質。>

    問題が発生した場合

    トランザクションログの最初の物理VLFが非アクティブでない場合、トランザクションログはラップアラウンドできないため、大きくなります(そうするように構成されていて、十分なディスク容量がある場合)。これは、ログの切り捨てによってVLFが非アクティブ化されるのを妨げる何かがあるためによく発生します。データベースのトランザクションログが増大していることがわかった場合は、SQL Serverにクエリを実行して、以下の簡単なコードを使用してログの切り捨ての問題があるかどうかを確認できます。

    SELECT
          [log_reuse_wait_desc]
      FROM [master].[sys].[databases]
      WHERE [name] = N'MyDatabase';

    ログの切り捨てによって1つ以上のVLFを非アクティブ化できた場合、結果は何もありません。それ以外の場合 、ログの切り捨てでVLFを非アクティブ化できなかった理由が表示されます。 ログの切り捨てを遅らせる可能性のある要因のセクションで説明されている考えられる理由の長いリストがあります。

    結果が何であるかのセマンティクスを理解することが重要です。これが、ログの切り捨てが最後に実行しようとしたときに何もできなかった理由です。 。たとえば、結果は ACTIVE_BACKUP_OR_RESTOREのようになります。 しかし、あなたはその長期実行の完全バックアップが終了したことを知っています。これは、ログの切り捨てが最後に試行されたときに、バックアップがまだ実行中であったことを意味します。

    私の経験では、ログの切り捨てが防止される最も一般的な理由は、 LOG_BACKUPです。;つまり、ログバックアップを実行してください!ただし、 LOG_BACKUP には、興味深い奇妙な動作もあります。 。結果が継続的に表示される場合LOG_BACKUP ただし、ログバックアップが正常に実行されていることはご存知でしょう。これは、データベース内のアクティビティがほとんどなく、現在のVLFが前回ログバックアップが実行されたときと同じであるためです。したがって、 LOG_BACKUP 「ログバックアップを実行する」または「バックアップされたすべてのログレコードは現在のVLFからのものであるため、非アクティブ化できませんでした」という意味です。後者が発生すると、混乱する可能性があります。

    循環…

    トランザクションログの循環的な性質を維持することは、コストのかかるログの増加と修正措置を講じる必要性を回避するために非常に重要です。通常、これは、ログの切り捨てを容易にするためにログのバックアップが定期的に行われるようにし、トランザクションログのサイズを変更して、ログの増加を発生させることなく、インデックスの再構築やETL操作などの大規模で長時間実行される操作を保持できるようにすることを意味します。

    シリーズの次のパートでは、ログレコード、それらがどのように機能するか、およびいくつかの興味深い例について説明します。


    1. SQLite-CSVファイルからデータをインポートする

    2. カンマ区切り値でいっぱいのvarcharをSQLServerIN関数に渡す

    3. MariaDBでのMAKETIME()のしくみ

    4. SQLクエリデータをExcelにエクスポートする