Đáng buồn thay, backupset
không chứa các bản sao lưu thất bại và tôi không biết bất kỳ nơi nào khác trong msdb
số này có thể được lưu trữ, trừ khi bạn có thể dựa vào sysjobhistory
, không chứa tất cả thời gian (tùy thuộc vào cài đặt duy trì của bạn) và sẽ bỏ qua mọi thứ các nỗ lực sao lưu được thực hiện bên ngoài bối cảnh của một công việc, và trong trường hợp một công việc sao lưu nhiều cơ sở dữ liệu - sẽ không cung cấp sự khác biệt về cơ sở dữ liệu nào thực sự thất bại, trừ khi nó xảy ra sớm trong công việc - đây là bởi vì tin nhắn khá dài dòng nhưng bị cắt ngắn.
Nếu bạn hoàn toàn biết rằng Job n
chỉ sao lưu một cơ sở dữ liệu và mọi thất bại của công việc đó có nghĩa là cơ sở dữ liệu không được sao lưu (vì công việc cũng có thể thất bại sau khi sao lưu thành công, ví dụ: cố gắng thu nhỏ hoặc thực hiện bảo trì khác), sau đó bạn có thể sử dụng một truy vấn như thế này:
DECLARE @job SYSNAME, @db SYSNAME;
SELECT @job = N'Job 1', @db = N'db_name';
SELECT
bs.database_name,
bs.backup_start_date,
bs.backup_finish_date,
[Total Time] = CAST((DATEDIFF(SECOND, bs.backup_start_date,bs.backup_finish_date))
AS VARCHAR(30))+ ' secs',
CAST(bs.backup_size/1024/1024 AS NUMERIC(10,2)) AS 'Backup Size(MB)',
h.[message]
FROM msdb.dbo.sysjobhistory AS h
INNER JOIN msdb.dbo.sysjobs AS j
ON h.job_id = j.job_id
AND h.step_id = 0
LEFT OUTER JOIN msdb.dbo.backupset AS bs
ON bs.database_name = @db
AND ABS(DATEDIFF(SECOND, bs.backup_start_date, CONVERT(DATETIME,CONVERT(CHAR(8), h.run_date)
+ ' ' + STUFF(STUFF(RIGHT('0'+CONVERT(VARCHAR(6),h.run_time),6),3,0,':'),6,0,':')))) < 5
WHERE j.name = @job
ORDER BY bs.backup_start_date;
Vâng, nó thực sự xấu, bởi vì sysjobhistory
, trong SQL Server 2014 thậm chí, lưu trữ run_date
và run_time
dưới dạng các số nguyên riêng biệt. Tôi cá là bất cứ ai đưa ra quyết định đó vẫn ở trên nền tảng của phi tiêu trên toàn tòa nhà 35. Nó cũng cho rằng sao lưu là bước đầu tiên trong công việc, do đó, so với việc so sánh ngày / giờ khoa học để đảm bảo rằng chúng tôi đúng tương quan với thể hiện đúng của công việc với thể hiện đúng của bản sao lưu. Ồ, làm thế nào tôi muốn tôi có thể thiết kế lại lược đồ cho các bản sao lưu và công việc.
Nếu bạn muốn phạm vi rộng hơn ngoài công việc, bạn có thể tìm kiếm các bản sao lưu thất bại trong nhật ký lỗi Máy chủ SQL (nếu chúng chưa được chuyển đi):
EXEC sp_readerrorlog 0, 1, 'BACKUP failed'; -- current
EXEC sp_readerrorlog 1, 1, 'BACKUP failed'; -- .1 (previous)
EXEC sp_readerrorlog 2, 1, 'BACKUP failed'; -- .2 (the one before that)
....
(Nhưng tôi không biết một cách hay và dễ dàng để kết hợp đầu ra đó vào truy vấn hiện tại của bạn.)
Bạn cũng có thể tương quan các bản sao lưu thành công "thiếu" từ theo dõi mặc định, ví dụ:
DECLARE @path NVARCHAR(260);
SELECT
@path = REVERSE(SUBSTRING(REVERSE([path]),
CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM sys.traces
WHERE is_default = 1;
SELECT dt.DatabaseName, dt.StartTime, bs.backup_start_date, bs.backup_finish_date,
[Status] = CASE WHEN bs.backup_start_date IS NULL
THEN 'Probably failed'
ELSE 'Seems like success'
END
FROM sys.fn_trace_gettable(@path, 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 -- backup/restore events
AND UPPER(CONVERT(NVARCHAR(MAX),dt.TextData)) LIKE N'BACKUP%DATABASE%'
--AND dt.DatabaseName = N'db_name' -- to filter to a single database
--AND bs.database_name = N'db_name'
ORDER BY dt.StartTime;
Tất nhiên, điều này cũng dựa trên dữ liệu từ dấu vết mặc định đang quay vòng, tên cơ sở dữ liệu không bị thay đổi, v.v. Và thật không may, dấu vết mặc định không phân biệt giữa các bản sao lưu thành công và thất bại và thời gian bắt đầu sẽ không khớp chính xác với MSDB dữ liệu, nhưng miễn là bạn không chạy các bản sao lưu trong một vòng lặp, điều này sẽ ổn cho việc đánh cầu mắt. Tôi đã cố gắng kết hợp những vấn đề này vào truy vấn.
Cuối cùng, bạn có thể muốn sử dụng FULL OUTER JOIN
ở đó, trong trường hợp backupset có lịch sử lâu hơn dấu vết mặc định. Điều này thay đổi ngữ nghĩa của [Status]
một chút.
Bạn cũng có thể muốn thử điều khó chịu này , mặc dù tôi không gặp nhiều may mắn với nó. Tôi chỉ có thể thấy trạng thái hiện tại hoặc gần đây nhất, vì vậy chỉ có ích khi công việc thất bại lần trước khi nó chạy, và - như sysjobhistory
- không thể có được thông tin về bất kỳ bản sao lưu nào đã cố gắng nhưng không thông qua công việc.