1 麻煩的地方
在SQL Server的官方檔案里面可以看到備份和還原的表,但是這些表里面只能找到備份成功的相關資訊,無法找到備份失敗的記錄,比如msdb.dbo.backupset,對于一些監控系統未監控作業的情況下,想要監控資料庫備份任務執行失敗而觸發告警規則,有些麻煩,
但是SQL server內部是可以通過查詢errorlog來判斷資料庫備份作業是否成功:

2 獲取errorlog的trace表
我們可以借助sys.traces定位到errorlog的trace檔案路徑,然后通過再通過fn_trace_gettable將errlog的trace檔案轉換為普通的表來查詢即可,
- 定位errorlog的trace檔案物理路徑
SELECT
REVERSE(
SUBSTRING(
REVERSE([path]),
CHARINDEX(CHAR(92), REVERSE([path])),
260
)
) + N'log.trc'
FROM
sys.traces
WHERE
is_default = 1
輸出結果:

2. 得到路徑后,使用fn_trace_gettable將errolog的trace檔案轉換為普通的資料表
SELECT
*
FROM
sys.fn_trace_gettable(
'S:\MSSQL13.MSSQLSERVER\MSSQL\Log\log.trc',
default
)

3. 查找與備份相關的事件記錄,在trace檔案中對應的EventClass為115,并將所有備份開頭的陳述句篩選出來
SELECT
TextData,Databasename,StartTime
FROM
sys.fn_trace_gettable(
'S:\MSSQL13.MSSQLSERVER\MSSQL\Log\log.trc',
default
)
WHERE
EventClass = 115
AND UPPER(CONVERT(nvarchar(max), TextData)) LIKE 'BACKUP%'

從回傳的TextData中沒有找到是否關于備份成功或者失敗的說明,也沒有在其它列中找到相關描述,需要結合msdb.dbo.backupset來判斷,
3 結合備份表backupset,判斷備份狀態
- 篩選出所有資料庫的備份任務執行情況

從查詢的結果可知,每個成功的備份都有1個開始時間和結束時間,考慮將開始時間與trace檔案轉換的表進行對比:
形成了具體的思路后,下面將trace轉換的表的StartTime列與backupset表的backup_start_date列進行對比判斷
2. 判斷存在對應的值則說明備份成功,不存在則備份失敗
SELECT
dt.DatabaseName,
dt.StartTime,
bs.backup_start_date,
bs.backup_finish_date,
[Status] = CASE
WHEN bs.backup_start_date IS NULL THEN (dt.DatabaseName) + '資料庫備份失敗'
ELSE (dt.DatabaseName) + '資料庫備份成功'
END
FROM
sys.fn_trace_gettable(
'S:\MSSQL13.MSSQLSERVER\MSSQL\Log\log.trc',
default
) AS dt
LEFT OUTER JOIN msdb.dbo.backupset AS bs ON dt.DatabaseName = bs.database_name
AND ABS(
DATEDIFF(SECOND, dt.StartTime, bs.backup_start_date)
) < 5
WHERE
dt.EventClass = 115
AND UPPER(CONVERT(nvarchar(max), dt.TextData)) LIKE N'BACKUP%'
ORDER BY
dt.StartTime DESC;

4 形成用于告警的SQL陳述句
完成上面的操作之后,我們已經能夠看到所有資料庫的備份是成功還是失敗的狀態,現在還需要將SQL再度細化,輸出所有資料庫最近一次備份執行成功或者失敗的資訊:即每個資料庫只有一行記錄用于說明最近一次的備份狀態,
下面有兩種寫法可以實作,第1種是游標的寫法,性能極差,后來找chatgpt一起討論之后,采用了group by優化,形成第2種寫法,
- 第1種,游標查看每個資料庫最近一次備份狀態
點擊查看代碼
DBCC FREE
DECLARE @databaseName1 nvarchar(100)
DECLARE @sql nvarchar(4000)
DECLARE db_cursor CURSOR FOR
SELECT name
FROM sys.databases
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @databaseName1
WHILE @@FETCH_STATUS = 0
BEGIN
SET @sql = '
SELECT
TOP 1 dt.DatabaseName,
dt.StartTime,
bs.backup_start_date,
bs.backup_finish_date,
[Status] = CASE
WHEN bs.backup_start_date IS NULL THEN (dt.DatabaseName) + ''資料庫備份失敗''
ELSE (dt.DatabaseName) + ''資料庫備份成功''
END
FROM
sys.fn_trace_gettable(
(
SELECT
REVERSE(
SUBSTRING(
REVERSE([path]),
CHARINDEX(CHAR(92), REVERSE([path])),
260
)
) + N''log.trc''
FROM
sys.traces
WHERE
is_default = 1
),
default
) AS dt
LEFT OUTER JOIN msdb.dbo.backupset AS bs ON dt.DatabaseName = bs.database_name
AND ABS(
DATEDIFF(SECOND, dt.StartTime, bs.backup_start_date)
) < 5
WHERE
dt.EventClass = 115
AND UPPER(CONVERT(nvarchar(max), dt.TextData)) LIKE N''BACKUP%''
AND dt.DatabaseName=''' + @databaseName1 +''' ORDER BY dt.StartTime DESC'
EXEC sp_executesql @sql
FETCH NEXT FROM db_cursor INTO @databaseName1
END
CLOSE db_cursor
DEALLOCATE db_cursor
可以看到性能極差,查詢3條資料耗時24秒,每次游標都要到消耗臨時表和進行大量的邏輯讀取,
點擊查看消耗的資源
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 14,邏輯讀取 36 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 98 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 2,邏輯讀取 30 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 7,邏輯讀取 42 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 1,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 31 毫秒,占用時間 = 27 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 2,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 1,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 16 毫秒,占用時間 = 23 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
(1 行受影響)
表 'backupset',掃描計數 1,邏輯讀取 3 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 468 毫秒,占用時間 = 678 毫秒,
SQL Server 執行時間:
CPU 時間 = 468 毫秒,占用時間 = 678 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 2,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 1,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 16 毫秒,占用時間 = 23 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
(0 行受影響)
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 406 毫秒,占用時間 = 732 毫秒,
SQL Server 執行時間:
CPU 時間 = 406 毫秒,占用時間 = 732 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 2,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 1,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 16 毫秒,占用時間 = 21 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
(0 行受影響)
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 422 毫秒,占用時間 = 659 毫秒,
SQL Server 執行時間:
CPU 時間 = 422 毫秒,占用時間 = 660 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 2,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 1,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 15 毫秒,占用時間 = 616 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
(0 行受影響)
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 375 毫秒,占用時間 = 678 毫秒,
SQL Server 執行時間:
CPU 時間 = 375 毫秒,占用時間 = 678 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 2,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 1,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 16 毫秒,占用時間 = 1286 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
(1 行受影響)
表 'backupset',掃描計數 1,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 375 毫秒,占用時間 = 781 毫秒,
SQL Server 執行時間:
CPU 時間 = 375 毫秒,占用時間 = 781 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 2,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 1,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 31 毫秒,占用時間 = 1608 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 13 毫秒,占用時間 = 13 毫秒,
(1 行受影響)
表 'backupset',掃描計數 1,邏輯讀取 3 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 390 毫秒,占用時間 = 737 毫秒,
SQL Server 執行時間:
CPU 時間 = 406 毫秒,占用時間 = 751 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysobjvalues',掃描計數 2,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syspalvalues',掃描計數 0,邏輯讀取 14 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysguidrefs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysclsobjs',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'syssingleobjrefs',掃描計數 1,邏輯讀取 6 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'sysdbreg',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 16 毫秒,占用時間 = 20 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 12 毫秒,占用時間 = 12 毫秒,
(0 行受影響)
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 468 毫秒,占用時間 = 2492 毫秒,
SQL Server 執行時間:
CPU 時間 = 484 毫秒,占用時間 = 2505 毫秒,
表 'Worktable',掃描計數 0,邏輯讀取 2 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
(1 行受影響)
SQL Server 執行時間:
CPU 時間 = 16 毫秒,占用時間 = 23 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,

- 第2種,使用MAX函式和group by優化
SELECT
[Status] = MAX(CASE
WHEN bs.backup_start_date IS NULL THEN dt.DatabaseName+'資料庫備份失敗'
ELSE dt.DatabaseName+'資料庫備份成功'
END)
FROM
sys.fn_trace_gettable(
(
SELECT
REVERSE(
SUBSTRING(
REVERSE([path]),
CHARINDEX(CHAR(92), REVERSE([path])),
260
)
) + N'log.trc'
FROM
sys.traces
WHERE
is_default = 1
),
default
) AS dt
LEFT OUTER JOIN msdb.dbo.backupset AS bs ON dt.DatabaseName = bs.database_name
AND ABS(DATEDIFF(SECOND, dt.StartTime, bs.backup_start_date)) < 5
WHERE
dt.EventClass = 115
AND UPPER(CONVERT(nvarchar(max), dt.TextData)) LIKE 'BACKUP%'
GROUP BY
dt.DatabaseName
這次執行只要1秒鐘,占用的資源也極低,
SQL Server 分析和編譯時間:
CPU 時間 = 15 毫秒,占用時間 = 20 毫秒,
(3 行受影響)
表 'Worktable',掃描計數 0,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
表 'backupset',掃描計數 1,邏輯讀取 48 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次,
SQL Server 執行時間:
CPU 時間 = 469 毫秒,占用時間 = 935 毫秒,
SQL Server 分析和編譯時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,
SQL Server 執行時間:
CPU 時間 = 0 毫秒,占用時間 = 0 毫秒,

截止到此,基本大功告成了,接下來要實作的就是監控系統怎么取得指標和觸發告警,具體可以根據不同的監控平臺進行配置,
實際上還可以通過xp_readerrorlog來讀取errorlog更加快速得篩選出備份失敗的記錄,但本次沒有再測驗,有興趣的朋友可以自行參考測驗,

5 使用xp_readerrorlog監控準確性更高
2023年5月10日增加:??在實際生產環境中,我們發現使用了NBU類的備份系統對資料庫進行備份時,NBU備份的啟動時間在log trace的時間要晚了10幾秒,這就導致上面的腳本判斷失敗了,最后確定通過xp_readerrorlog來讀取errorlog,確保監控資料的準確性,參考腳本:
DECLARE @Logs TABLE
(
LogDate DATETIME,
ProcessInfo NVARCHAR(24),
Text VARCHAR(1000)
)
INSERT INTO @Logs EXEC sp_readerrorlog 0, 1, N'Backup failed'
DECLARE @keyword VARCHAR(50);
DECLARE @num_keywords INT;
DECLARE @i INT;
SET @num_keywords = (SELECT COUNT(*) FROM sysdatabases);
SET @i = 1;
WHILE (@i <= @num_keywords)
BEGIN
SET @keyword = (SELECT name FROM sysdatabases WHERE dbid = @i);
SELECT TOP 1 LogDate,SUBSTRING([Text], PATINDEX('%' + @keyword + '%', [Text]), LEN(@keyword))+'備份失敗' AS Result
FROM @Logs
WHERE PATINDEX('%' + @keyword + '%', [Text]) > 0
ORDER BY LogDate DESC;
SET @i = @i + 1;
END;

轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/552168.html
標籤:其他
上一篇:基于華為云圖引擎GES,使用Cypher子查詢進行圖探索
下一篇:返回列表
