web-dev-qa-db-ja.com

トランザクションレプリケーションを使用してデータベースで1回限りのログ圧縮を行う方法

80 GBのログを含む10 GBのデータベースを継承しました[DBCC SQLPERF(logspace)によると、使用中の3%のみ]。極端なログの増加は、私が採用されるずっと前からの問題が原因であると想定するのは安全に思われます。

プライマリには、15分ごとに実行されるログ配布バックアップジョブがあります。プライマリには、15分ごとに実行されるコピージョブと復元ジョブがあります。

ログを圧縮しようとすると、「ファイルの最後にある論理ログファイルが使用中のため、ログファイル2(DatabaseName_log)を圧縮できません。」というメッセージが表示されます。私はこれを15分間隔で、さらには数日間隔で数回再試行しましたが、常に同じ結果が得られます。

DBCC LOGINFOは784のVLFを表示し、最初の245と最後のステータスのみが2の状態で表示されます。 ODBCドライバの問題)でアプリにアクセスします。

このログを正常に縮小するにはどうすればよいですか(ユーザーの停止を作成せずに)?

ありがとう、マーク

2
Mark Freeman

この問題の最も簡単な解決策は、データベースを単純復旧に設定し、ログを圧縮してから、完全復旧に戻すことです。 T-SQLでは、これは次のようになります。

ALTER DATABASE [database] SET RECOVERY SIMPLE WITH NO_WAIT
DBCC SHRINKFILE([logfilename], 1)
ALTER DATABASE [database] SET RECOVERY FULL WITH NO_WAIT

データベースを単純復旧に変更すると、トランザクションの複製が停止する可能性がありますが、営業時間外にスケジュールされている場合は、ログが縮小され、副作用のない完全復旧に戻るはずです。

これが受け入れられない場合は、sp_repldoneストアドプロシージャを使用して、手動でトランザクションを分散としてマークし、無効なトランザクションのレプリケーションステータスをリセットできます。

EXEC sp_repldone @xactid = NULL, @xact_segno = NULL, @numtrans = 0,    @time = 0, @reset = 1
7
dartonw

このようなスクリプトを実行して、完了するまで1分ごとに縮小操作を試みるか、1,000回実行する可能性があります。 いつものように、あなた自身の責任で使用してください-そして、これを最初に非運用環境でテストしてください。

USE tempdb;  /*  CHANGE THIS TO DESIRED DATABASE */
GO
DECLARE @DesiredSizeInMB INT;
SET @DesiredSizeInMB = 1;

DECLARE @T TABLE (
    CurrentSize BIGINT
);
DECLARE @LogFileName VARCHAR(255);
DECLARE @LoopCount INT;
DECLARE @MaxLoops INT;
DECLARE @OK BIT;

SELECT @LogFileName = df.name
FROM sys.database_files df
WHERE df.type_desc = 'LOG';

SET @LoopCount = 0;
SET @MaxLoops = 1000;
WHILE @LoopCount < @MaxLoops
BEGIN
    SET @OK=1;
    BEGIN TRY
        DELETE FROM @T;
        INSERT INTO @T
        SELECT size * 8192 / 1048576E0
        FROM sys.database_files df
        WHERE df.type_desc = 'LOG';
        DBCC SHRINKFILE (@LogFileName, @DesiredSizeInMB);
        /* If the now-current size of the log file is with 1MB of the target size, break */
        IF (SELECT CurrentSize * 8192 / 1048576E0 FROM @T) <= @DesiredSizeInMB + 1 
            BREAK;
        ELSE
            SET @OK = 0;
    END TRY
    BEGIN CATCH
        SET @OK=0;
        PRINT ERROR_MESSAGE();
    END CATCH
    IF @OK = 1 BREAK; /* IF the command didn't fail, then exit the loop */
    WAITFOR DELAY '00:00:30'
    SET @LoopCount = @LoopCount +1;
END
2
Max Vernon

VMテストサーバーでバックアップ計画をテストするとき、バックアップを実行していて、shrinkコマンドのみを使用しました。SIMPLEリカバリモデルを使用していますが、それでも強制する必要がありました。データベースをSIMPLEモードに設定した場合にのみ、t-logを圧縮できます。結論として、データベースがSIMPLEリカバリモデルであり、FULLではない場合は、次のコマンドが必要であると思われます。ALTER DATABASE [database] SET RECOVERY SIMPLE WITH NO_WAIT DBCC SHRINKFILE([ログファイル名]、1)

0
Ryszard