サーバー上のすべてのデータベースの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
私は、dbatoolsモジュールのGet-DbaLastGoodCheckDbからPowerShellコマンドを使用して、すべてのサーバーを一度にチェックできるようにします。
コマンドの出力例は次のとおりです
このような詳細な情報を得ることができます
このようなサーバー全体をチェックして
それも本当に速いです。 125のデータベースを備えた10台のサーバーの私のラボでは、5.3秒で完了します
https://dbatools.io でdbatoolsの詳細を読むことができます。
アーロンが説明したように問題のある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ページには、カーソルオプションに関する優れた詳細があり、読んで理解する価値があります。
異なるフレーバーと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
}
以下は出力です( クリックして拡大 ):
検討する必要がある/注意する必要のあるものの組み合わせ:
dbi_dbccLastKnownGood
は更新されません。Robert Davis は、DBCC CHECKFILEGROUP
がdbi_dbccLastKnownGood
をDBCC CHECKDB
とともに更新することをブログに投稿しました。