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

SQL Serverトランザクションログ—パート1

    すべてのSQLServerデータベースには、データファイルに加えて1つ以上のトランザクションログファイルが含まれています。ログファイルには、すべてのトランザクションと、それぞれによって行われたデータベースの変更が記録されます。

    この記事では、トランザクションログと、SQLServerがデータベースのクラッシュリカバリにデータを使用するためにデータの変更をログに記録する方法に焦点を当てています。

    SQLServerトランザクションログファイルの概要

    私たちが覚えているように、各トランザクションは「オールオアナッシング」です。トランザクションの一部が失敗すると、トランザクション全体が失敗し、データベースの状態は変更されません。

    SQL Serverは、データベースで実行された各トランザクションの記録をログファイルに保存します。 SQL Serverのシャットダウンを伴う災害が発生した場合は、トランザクションログを使用して、データベースをデータの整合性を備えた一貫性のある状態に回復します。

    再起動後、SQLServerはクラッシュリカバリプロセスを開始します。トランザクションログファイルを読み取り、すべての有効なデータがデータファイルに保存されていることを確認し、コミットされていないトランザクションがロールバックされます。

    通常の操作中、SQLServerはトランザクションログも使用します。ファイルに含まれる情報は、エラーまたはユーザー指定のROLLBACKステートメントのいずれかが原因でトランザクションがロールバックされたときにSQLServerが実行する必要があることを識別するために必要です。

    SQLServerがトランザクションログを使用する方法

    トランザクションログは、拡張子が LDFの物理ファイルです。 。 SQL Serverは、プライマリデータファイル(。 MDF )とともに新しいデータベース用に自動的に作成します )データベースオブジェクトとデータ自体を格納します。

    T-SQLコードがデータベースオブジェクトまたはそれに含まれるデータを変更するたびに、変更の詳細がトランザクションログファイルにログレコードとして記録されます。

    ログレコードには、データベースに加えられた特定の変更に関する情報が含まれています(たとえば、単一の行を挿入します)。したがって、単一のトランザクションの影響を完全に説明する一連のログレコードがあります。

    トランザクションログアーキテクチャ

    ログシーケンス番号

    ログレコードには、一意の自動インクリメントログシーケンス番号( LSN )があります )、これにより、トランザクションログでこのレコードを見つけることができます。 LSNはデータの変更について説明し、次の情報が含まれています。

    • 操作と影響を受ける行
    • データの新旧バージョン
    • 変更を実行したトランザクション

    LSNは3つの数字で構成されています:

    LSN =:<ログブロック#[4バイト]>:<ログレコード#[2ビュー]>

    各データファイルページのページヘッダーには、変更がページに反映されている最新のログレコードを識別するLSNがあります。これはクラッシュリカバリにとって重要です。

    クラッシュリカバリが実行されると、コミットまたは非コミットトランザクションのログレコードのLSNがデータファイルページのLSNと比較され、それらの特定のログレコードに対して実行するREDOまたはUNDOがあるかどうかが判断されます。

    データベースを作成するときは、トランザクションログのサイズを指定することをお勧めします。 。これを行わないと、SQLServerはデフォルトのサイズでトランザクションログを自動的に作成します。

    トランザクションログのデフォルトサイズ 新しいデータベースのサイズは0.5MBの大きい方です または25% 同じCREATEDATABASEステートメントで作成されたすべてのデータファイルの合計サイズ。

    トランザクションログの新しい部分は常にゼロ初期化されるため、十分に注意する必要があります。 。ログファイルのサイズを指定せずにCREATEDATABASEステートメントがあり、たとえば1TBのデータベースを作成した場合、SQLServerは250GBのトランザクションログを作成します。

    ログはゼロで初期化する必要があるため、ファイルの即時初期化は使用されません。この機能はSQLServer2005で追加され、データファイルをほぼ瞬時に作成または拡張できるようになりました。

    CREATE DATABASEを実行すると、何が起こっているかを確認できます。 trace flag 3004 を使用して、ログの初期化がゼロになります。 これは、ゼロ初期化とトレースフラグ3605に関するメッセージを出力します。 これにより、トレースフラグ3004によってこれらのログメッセージを印刷できます。

    次のデモは、ログファイルのゼロ化が発生していることを確認する方法を示しています。

    1.次のスクリプトを実行して、DBTest2014というデータベースがないことを確認します

    USE master;
    GO
     
    IF DATABASEPROPERTY(N'DBTest2014', N'Version')>0
      BEGIN
        ALTER DATABASE DBTest2014 SET SINGLE_USER
          WITH ROLLBACK IMMEDIATE;
        DROP DATABASE DBTest2014;
      END
    GO
    

    2.トレースフラグを有効にして、ゼロ初期化を監視します

    DBCC TRACEON (3605, 3004, -1);
    GO
    3. Flush the error log
    EXEC sp_cycle_errorlog;
    GO
    

    3.データベースを作成します

    CREATE DATABASE DBTest2014 ON PRIMARY (
      NAME = N'DBTest2014',
      FILENAME = N'D:\DBTest2014_data.mdf')
    LOG ON (
      NAME= N'DBTest2014_log',
      FILENAME= N'D:\DBTest2014_log.ldf',
      SIZE = 10MB,
      FILEGROWTH = 10 MB);
    GO
    

    4.エラーログファイルを読み取ります

    EXEC sys.xp_readerrorlog;
    GO
    

    仮想ログファイル

    トランザクションログは、内部で仮想ログファイルと呼ばれる一連のチャンクに分割されます。 ( VLF )管理を簡素化するため。

    トランザクションログが作成されるたびに、特定の数のVLFが提供されます。新しく作成されたVLFは非アクティブで、使用されていません。アクティブなVLFは、ログのクリアによって非アクティブになるまで再利用できません。

    ただし、例外が1つあります。トランザクションログには少なくとも1つのアクティブなVLFが必要であるため、新しいデータベースの最初のVLFは常にアクティブです。

    すべてのログファイルには、ファイルヘッダーページもあります 8KBかかります トランザクションログファイルの開始時。ファイルヘッダーページには、サイズや自動拡張設定など、ファイルに関するメタデータが保存されます。

    トランザクションログの新しい部分にあるVLFの数とサイズは、SQLServerによって決定されます。設定することはできません

    新しく追加されたサイズが次の場合:

    • <1MBは議論には関係ありません
    • <64MBには4つの新しいVLFがあります(それぞれ成長サイズの1/4)
    • 64MBから1GBには、8つの新しいVLFがあります(それぞれ成長サイズの1/8)
    • > 1GBには16個の新しいVLFがあります(それぞれ成長サイズの1/16)

    これは、最初に作成されたトランザクションログと、発生する手動または自動の拡張ごとに適用されます。 VLFの潜在的な数とその潜在的なサイズの式がわかっている場合は、ログの管理に役立ちます。 VLFが少なすぎたり多すぎたりすると、トランザクションログ操作でパフォーマンスの問題が発生する可能性があります。

    VLFシーケンス番号

    すべてのVLFには、トランザクションログ内でVLFを一意に識別するためのシーケンス番号があります。ログ管理システムが次のVLFをアクティブ化するたびに、シーケンス番号が1つずつ増加します。シーケンス番号のチェーンは、現在アクティブなVLFのセットを提供します。

    トランザクションログのアクティブな部分の開始は、シーケンス番号が最も小さく、まだアクティブなVLFで始まります。非アクティブなVLFにはシーケンス番号がありますが、ログアクティブ部分の一部ではありません。

    ログのアクティブな部分には、SQLServerが何らかの理由で必要とするログレコードがあります。

    新しいデータベースを最初に作成するとき、VLFシーケンス番号は1から始まりません。これらは、モデルデータベーストランザクションログにある最大のVLFシーケンス番号に1を加えたもので始まります。 。 VLFシーケンス番号を使い果たすことは不可能です。 SQL Serverには、VLFシーケンス番号がゼロにラップアラウンドした場合(次のVLFシーケンス番号が前のシーケンス番号よりも小さい場合)にインスタンスを強制的にシャットダウンするコードがあります。

    VLFおよびログブロック

    VLF内には、さまざまなサイズのログブロックがあります。 ログブロックの最小サイズは512です バイトとログブロックは、最大サイズ60 KBまで増加します。 。サイズは、次のいずれかの場合に設定されます。

    • トランザクションは、トランザクションの中止を終了するためにコミットするログレコードを生成します
    • トランザクションをコミットまたは中止せずにログブロックサイズが60KBに達する

    ログブロック内にログレコードがあります(図の色付き)。ログレコードのサイズもさまざまです。この図は、複数の同時トランザクションからのログレコードが同じログブロック内に存在できることを示しています。ログレコードは、データページファイルと同様に書き込まれた順序で保存されます。

    すべてのVLFには、次の情報を含むVLFヘッダーが含まれています。

    • VLFがアクティブかどうか。
    • VLFが作成されたときのログシーケンス番号。
    • VLF内のすべての512バイトブロックの現在のパリティビット。

    パリティビットは、初めてVLFを使用するときに64から始まります。 VLFが非アクティブになったが、さらに再アクティブ化された場合、パリティビットは128になります。これらはクラッシュリカバリ中に使用されます。

    トランザクションログの詳細の調査– DBCC LOGINFO

    トランザクションログ構造を確認する唯一の方法は、文書化されていない DBCC LOGINFOを使用することです。 指図。コマンドの構文は次のとおりです。

    DBCC LOGINFO [({'dbname | dbid'})]

    dbnameを指定しない場合 および入札 、現在のデータベースのログの内容をダンプします。

    結果は、そのデータベースのトランザクションログにあるVLFごとに1行になります。返されるフィールドは次のとおりです。

    • RecoveryUnitId — SQL Server 2012で追加されましたが、現在は使用されていません
    • FileId —データベース内のトランザクションログファイルID。
    • FileSize —バイト単位のVLFサイズ。
    • StartOffset —トランザクションログファイルのVLFの開始オフセット(バイト単位)
    • FSeqNo —VLFシーケンス番号
    • ステータス — VLFがアクティブかどうか(0 =非アクティブ、2 =アクティブ、1 –使用されない)
    • パリティ —現在のパリティビット(64または128、またはVLFがアクティブになったことがない場合は0)
    • CreateLSN — VLFが作成されたときのLSN(0 =トランザクションログファイルが最初に作成されたときにVLFが作成されました)。トランザクションログファイルの最初の作成後に追加された他のすべてのVLFには、ゼロ以外のCreateLSNが含まれます。

    DBTest2014に対して次のコマンドを実行できます 以前に作成したデータベース:

    DBCC LOGINFO (N'DBTest2014');
    GO
    

    結果を見る:

    DBCC SQLPERF(LOGSPACE)

    Transact-SQLで使用されるログの量を調べる唯一の方法は、DBCCSQLPERFです。コマンドの構文は次のとおりです。

    DBCC SQLPERF
    (
         [ LOGSPACE ]
         |
              [ "sys.dm_os_latch_stats" , CLEAR ]
         |
         [ "sys.dm_os_wait_stats" , CLEAR ]
    )
         [WITH NO_INFOMSGS ]
    

    このコマンドは、データベースごとに1行の結果セットを返します。

    • データベース名
    • ログサイズ(MB)
    • 使用されたログスペース(%)
    • ステータス:常にゼロに設定

    私の環境では、次のコマンド:

    DBCC SQLPERF (LOGSPACE);
    GO
    

    次の結果を返します:

    次の記事では、ログレコードを調べます。


    1. ブールサポートOracleSQL

    2. 多くの列を持つクエリで単一の列を集約します

    3. 外部キー参照アクションを変更するにはどうすればよいですか? (行動)

    4. SQLServerデータベースの列を含むすべてのデフォルトの制約を一覧表示する方法-SQLServer/TSQLチュートリアルパート92