DBCC CHECKDB LastKnownGood

Gor*_*ell 4 sql-server t-sql dbcc-checkdb

我创建了以下查询来列出服务器上所有数据库的 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
Run Code Online (Sandbox Code Playgroud)

SQL*_*ard 8

我将使用 dbatools 模块 Get-DbaLastGoodCheckDb 中的 PowerShell 命令,这将使您能够一次性检查所有服务器。

这是命令的示例输出

在此处输入图片说明

您可以获得这样的详细信息

在此处输入图片说明

并像这样检查一大堆服务器

在此处输入图片说明

它也真的很快。在我的 10 个服务器和 125 个数据库的实验室中,它在 5.3 秒内完成

您可以在https://dbatools.io 上阅读有关 dbatools 的更多信息


Han*_*non 7

sp_msForEachdb您可以使用游标来代替Aaron 描述的有问题的 。

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;
Run Code Online (Sandbox Code Playgroud)

此输出具有数据库名称以及来自 DBCC DBINFO 输出的 LastKnownGood 列作为DATETIME变量。不“在线”的数据库包含在输出中,LastKnownGoodDBCC列设置为NULL.

在我上面的例子中创建的游标是一个非常高效的本地、只进、静态游标。Local 表示游标的范围仅限于我们的会话,这显然不是问题(sp_msForEachdb 使用了一个设置起来非常昂贵的全局游标)。只进选项表示我们不打算通过游标向后滚动,并允许 SQL Server 使用只进、只读游标语义。静态选项强制 SQL Server 将游标结果具体化到 tempdb 中的临时表中,并从那里读取每一行。DECLARE CURSOR上的 MSDN 页面有关于游标选项的精彩细节,非常值得阅读和理解。