トランザクションログの操作の合理化に関する以前の投稿では、余分なログレコードが生成される最も一般的な原因の2つ、未使用の非クラスター化インデックスによる自重とページ分割操作(インデックスの断片化を引き起こす)について説明しました。その投稿を読んだと仮定して、トランザクションログのパフォーマンスに悪影響を与える可能性のあるより微妙な問題があることを述べました。ここで、これらについて説明します。
非常に多くの小さなトランザクション
SQL Serverは、トランザクションログの一部をディスクにフラッシュすることがよくあります。ログフラッシュは次の場合に発生します:
- トランザクションコミットログレコードが生成されます。
- トランザクションアボートログレコードは、トランザクションロールバックの最後に生成されます。
- 前回のログフラッシュ以降、60KBのログレコードが生成されています。
可能な最小のログフラッシュは、単一の512バイトのログブロックです。ワークロード内のすべてのトランザクションが非常に小さい場合(たとえば、単一の小さなテーブル行を挿入する場合)、最小サイズのログフラッシュが多数発生します。ログフラッシュは、適切なトランザクションログスループットを可能にするために非同期で実行されますが、一度に32の同時ログフラッシュI / Oの固定制限があります(SQL Server 2012では112に引き上げられます)。
これには2つの考えられる影響があります:
- パフォーマンスの遅いI/Oサブシステムでは、小さなトランザクションログ書き込みの量がI / Oサブシステムを圧倒し、書き込みの待ち時間が長くなり、トランザクションログのスループットが低下する可能性があります。この状況は、sys.dm_io_virtual_file_statsの出力にあるトランザクションログファイルの書き込みレイテンシが高いことで識別できます(前の投稿の上部にあるデモリンクを参照してください)
- 高性能のI/Oサブシステムでは、書き込みは非常に迅速に完了する場合がありますが、ログレコードをディスク上で永続的にしようとすると、32の同時ログフラッシュI/Oの制限がボトルネックになります。この状況は、書き込み待ち時間が短く、sys.dm_io_pending_io_requestsの集計出力で32に近い未処理のトランザクションログ書き込みの数がほぼ一定であることで識別できます(同じデモリンクを参照)。
どちらの場合も、トランザクションを長くすると(非常に直感に反します!)、トランザクションログのフラッシュの頻度を減らしてパフォーマンスを向上させることができます。さらに、ケース#1の場合、パフォーマンスの高いI / Oサブシステムに移行すると役立つ場合がありますが、ケース#2につながる可能性があります。ケース2の場合、トランザクションを長くできない場合、唯一の代替策は、ワークロードを複数のデータベースに分割して、32の同時ログフラッシュI / Oの固定制限を回避するか、SQLServer2012以降にアップグレードすることです。
トランザクションログの自動拡張
トランザクションログに新しいスペースが追加されるたびに、インスタントファイル初期化機能が有効になっているかどうかに関係なく、ゼロで初期化する必要があります(ディスクのその部分の以前の使用を上書きするためにゼロを書き出す)。これは、トランザクションログの作成、手動拡張、および自動拡張に適用されます。ゼロ初期化が行われている間、ログレコードをログにフラッシュすることはできないため、データを変更しているワークロード中の自動拡張は、特に自動拡張サイズが大きく設定されている場合、スループットの顕著な低下につながる可能性があります(ギガバイトと言うか、デフォルトの10%のままにしておきます。
可能であれば、トランザクションログをクリアして、新しいログレコードに再利用できる空き領域が常に存在するようにすることで、自動拡張を回避する必要があります。トランザクションログのクリア(トランザクションログの縮小とも呼ばれ、トランザクションログの縮小と混同しないでください)は、フルログまたはバルクログのリカバリモードを使用する場合はトランザクションログのバックアップによって、シンプルリカバリモードを使用する場合はチェックポイントによって実行されます。
>ログのクリアは、トランザクションログのセクションのログレコードをクリアする必要がない場合にのみ発生します。ログのクリアを妨げる一般的な問題の1つは、トランザクションが長時間実行されることです。トランザクションがコミットまたはロールバックされるまで、トランザクションがロールバックする場合に備えて、トランザクションの開始以降のすべてのログレコードが必要です。これには、長時間実行されるトランザクションのログレコードが散在している他のトランザクションのすべてのログレコードが含まれます。長時間実行されるトランザクションは、たとえば、不十分な設計、人間の入力を待機しているコード、またはネストされたトランザクションの不適切な使用が原因である可能性があります。問題として特定されると、これらすべてを回避できます。
これについて詳しくは、こちらとこちらをご覧ください。
高可用性機能
一部の高可用性機能は、トランザクションログのクリアを遅らせる可能性もあります:
- データベースのミラーリングと可用性グループを非同期で実行すると、冗長データベースコピーにまだ送信されていないログレコードのキューが作成される可能性があります。これらのログレコードは、送信されるまで保持する必要があり、トランザクションログのクリアが遅れます。
- トランザクションレプリケーション(およびデータキャプチャの変更)は、ログリーダーエージェントジョブに依存して、レプリケーションパブリケーションに含まれるテーブルを変更するトランザクションのトランザクションログを定期的にスキャンします。 Log Reader Agentが何らかの理由で遅れたり、意図的に実行頻度が低くなったりした場合は、ジョブによってスキャンされていないすべてのログレコードを保持する必要があり、トランザクションログのクリアが遅れます。
同期モードで実行している場合、データベースのミラーリングと可用性グループにより、ロギングメカニズムで他の問題が発生する可能性があります。例として同期データベースミラーリングを使用すると、プリンシパルでコミットするトランザクションは、生成されたすべてのログレコードがミラーサーバーに正常に送信されるまで、実際にはユーザーまたはアプリケーションに戻ることができず、プリンシパルにコミット遅延が追加されます。平均トランザクションサイズが長く、遅延が短い場合、これは目立たない可能性がありますが、平均トランザクションが非常に短く、遅延が非常に長い場合、これはワークロードスループットに顕著な影響を与える可能性があります。その場合、ワークロードのパフォーマンス目標を変更するか、高可用性テクノロジーを非同期モードに変更するか、プリンシパルデータベースと冗長データベース間のネットワーク帯域幅と速度を上げる必要があります。
ちなみに、I / Oサブシステム自体が同期的にミラーリングされている場合も、同じ種類の問題が発生する可能性があります。SQLServerが実行するすべての書き込みに遅延が発生する可能性があります。
概要
ご覧のとおり、トランザクションログのパフォーマンスは、生成される追加のトランザクションログレコードだけではありません。深刻な影響を与える可能性のある多くの環境要因もあります。
結論として、トランザクションログの状態とパフォーマンスは、全体的なワークロードのパフォーマンスを維持するために最も重要です。これらの2つの投稿では、トランザクションログのパフォーマンスの問題の主な原因について詳しく説明したので、問題を特定して修正できることを願っています。
トランザクションログの操作とパフォーマンスの調整についてさらに詳しく知りたい場合は、Pluralsightから入手できる、ロギング、リカバリ、およびトランザクションログに関する7.5時間のオンライントレーニングコースを確認することをお勧めします。