web-dev-qa-db-ja.com

DBCC CHECKDB LastKnownGood

サーバー上のすべてのデータベースのDBCC CHECKDB LastKnownGoodタイムスタンプを一覧表示する次のクエリを作成しました。これを行うより良い方法はありますか?

IF OBJECT_ID(N'tempdb..#Results') IS NOT NULL
BEGIN
    DROP TABLE #Results
END

CREATE TABLE #Results (ParentObject varchar(100), Object varchar(100), Field varchar(100), Value varchar(100))
GO

INSERT INTO #Results
EXEC sp_msForEachdb @command1 = 'DBCC DBINFO (''?'') WITH TABLERESULTS'

ALTER TABLE #Results ADD ID INT IDENTITY(1, 1)
GO -- required here

SELECT r.Value as [Database], r2.Value as CheckDB_LastKnownGood
FROM #Results r
INNER JOIN #Results r2
ON r2.ID = (SELECT MIN(ID) FROM #Results WHERE Field = 'dbi_dbccLastKnownGood' AND ID > r.ID)
WHERE r.Field = 'dbi_dbname'
ORDER BY r.Value
4
Gordon Bell

私は、dbatoolsモジュールのGet-DbaLastGoodCheckDbからPowerShellコマンドを使用して、すべてのサーバーを一度にチェックできるようにします。

コマンドの出力例は次のとおりです

enter image description here

このような詳細な情報を得ることができます

enter image description here

このようなサーバー全体をチェックして

enter image description here

それも本当に速いです。 125のデータベースを備えた10台のサーバーの私のラボでは、5.3秒で完了します

https://dbatools.io でdbatoolsの詳細を読むことができます。

8

アーロンが説明したように問題のあるsp_msForEachdbを使用する代わりに、これにカーソルを使用できます。

IF OBJECT_ID(N'tempdb..#Results') IS NOT NULL
BEGIN
    DROP TABLE #Results;
END

CREATE TABLE #Results
(
    DatabaseName SYSNAME NULL
    , IsOnline BIT NULL
    , ParentObject varchar(100) NULL
    , [Object] varchar(100) NULL
    , [Field] varchar(100) NULL
    , [Value] varchar(100) NULL
);

DECLARE @cmd NVARCHAR(MAX);
DECLARE @dbName SYSNAME;
DECLARE @IsOnline BIT;

DECLARE cur CURSOR LOCAL FORWARD_ONLY STATIC
FOR
SELECT DBCCCommand = 'DBCC DBINFO(''' + d.name + ''') WITH TABLERESULTS;'
    , DatabaseName = d.name
    , IsOnline = CONVERT(BIT, 
        CASE WHEN d.state_desc = 'ONLINE' THEN 1 ELSE 0 END
      )
FROM sys.databases d
ORDER BY d.name;

OPEN cur;
FETCH NEXT FROM cur INTO @cmd, @dbName, @IsOnline;

WHILE @@FETCH_STATUS = 0
BEGIN
    RAISERROR (@dbName, 0, 1) WITH NOWAIT;
    IF @IsOnline = 1
    BEGIN
        INSERT INTO #Results (ParentObject, [Object], [Field], [Value])
        EXEC sp_executesql @cmd;
        UPDATE #Results 
        SET DatabaseName = @dbName
            , IsOnline = @IsOnline
        WHERE DatabaseName IS NULL;
    END
    ELSE
    BEGIN
        INSERT INTO #Results (DatabaseName, IsOnline)
        VALUES (@dbName, @IsOnline)
    END

    FETCH NEXT FROM cur INTO @cmd, @dbName, @IsOnline;
END

CLOSE cur;
DEALLOCATE cur;

SELECT r.DatabaseName
    , LastKnownGoodDate = CONVERT(DATETIME, r.value, 120)
    , r.IsOnline
FROM #Results r
WHERE r.field = 'dbi_dbccLastKnownGood'
    OR r.field IS NULL;

この出力には、DATETIME変数としてDBCC DBINFO出力からのLastKnownGood列と共にデータベース名が含まれます。 「オンライン」ではないデータベースが出力に含まれ、LastKnownGoodDBCC列がNULLに設定されます。

上記の例で作成されたカーソルは、非常に効率的なローカルの前方専用の静的カーソルです。ローカルは、カーソルのスコープがセッションに限定されていることを示します。これは明らかに問題ではありません(sp_msForEachdbは、設定に非常にコストがかかるグローバルカーソルを使用します)。前方のみのオプションは、カーソルを介して後方にスクロールできるようにするつもりがないことを示し、SQL Serverが前方のみの読み取り専用のカーソルセマンティクスを使用できるようにします。 staticオプションを使用すると、SQL Serverはカーソルの結果をtempdbの一時テーブルに具体化し、そこから各行を読み取ります。 DECLARE CURSOR のMSDNページには、カーソルオプションに関する優れた詳細があり、読んで理解する価値があります。

7
Max Vernon

異なるフレーバーとPowershellを学ぶ私の探求を追加するだけで...以下のコードを使用して同じことを達成できます(改善の余地はありますが、非常に短く、クリーンで、リストを提供できます)確認したいSQLサーバーの数)

<#  
    .NOTES
     ===========================================================================
     Created with:  SAPIEN Technologies, Inc., PowerShell Studio 2016 v5.2.115
     Created on:    3/29/2016 
     Created by:    Kin 
     Purpose:       For dba.stackexchange.com 
     Question:      http://dba.stackexchange.com/q/133687/8783      
     Reference:     https://www.mssqltips.com/sqlservertip/2948/check-dbcc-checkdb-last-execution-using-powershell/
     ===========================================================================
    .DESCRIPTION
        -   Reads the input from the user and connects to the sql server instance 
        -   Finds the "dbi_dbccLastKnownGood" along with the date
#>
cls
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | out-null

$YourSQLServerInstanceName = Read-Host -Prompt 'Input your sql server instance name  '
$serverInstance = New-Object ("Microsoft.SqlServer.Management.Smo.Server") $YourSQLServerInstanceName
foreach ($db in $serverInstance.Databases | Where-Object { ($_.IsAccessible -like "TRUE") -and ($_.Name -ne "tempdb")  })  #we ONLY want ONLINE databases and NO TEMPDB
{
    $lastDBCC_CHECKDB = $db.ExecuteWithResults("DBCC DBINFO () WITH TABLERESULTS").Tables[0] | where { $_.Field.ToString() -eq "dbi_dbccLastKnownGood" } 
    $lastDBCC_CHECKDB | select-object `
                        @{Label='Last DBCC CHECKDB execution'; Expression =$({$db.Name})}`
                        ,@{Label='DateTime';Expression=$({$lastDBCC_CHECKDB.Value[0]})} | Get-Unique    
}

以下は出力です( クリックして拡大 ):

enter image description here

検討する必要がある/注意する必要のあるものの組み合わせ:

  • データベースがREADONLYの場合、DBCC CHECKDBが正常に実行されても、dbi_dbccLastKnownGoodは更新されません。
  • Robert Davis は、DBCC CHECKFILEGROUPdbi_dbccLastKnownGoodDBCC CHECKDBとともに更新することをブログに投稿しました。

    enter image description here

4
Kin Shah