Sql-Server

從 SQL Server 2016 備份到 Azure URL 時備份文件失去

  • December 29, 2021

我有一個這樣的作業腳本,它應該使用儲存密鑰憑據將 SQL Server 2016 dbs 備份到 Azure blob 儲存。通常它工作正常,但有時會失去一些備份(我的意思是儲存帳戶上沒有備份文件)並且我沒有得到任何類型或作業失敗或作業日誌文件上的錯誤。數據庫只是被跳過。我注意到,當備份工作與維護程序重疊時,當我更改時間時,這種情況經常發生,它每月或更少發生一次。但我不確定維護(索引維護、dbcc、統計更新)是導致此異常的原因。

我想知道你之前有沒有這樣的經歷,可能知道核心原因是什麼?

有趣的部分是我恢復了verifyonly,它也只是跳過了數據庫。它不會嘗試恢復那些數據庫,這就是為什麼我沒有收到失敗錯誤,只是跳過

DECLARE @dbname sysname
DECLARE @path nvarchar(120)
DECLARE @credential sysname = 'BackupStorageCredential'
DECLARE @date nvarchar(250) = CAST( GETDATE() AS Date ) 
SET @path = N'[my_storage_url]'

DECLARE db_cursor CURSOR FOR
SELECT name FROM sys.databases
WHERE name IN ('db1','db2','db3')
OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @dbname   
WHILE @@FETCH_STATUS = 0   
BEGIN   
   DECLARE @query_backupToAzBLOB   NVARCHAR(max)
   DECLARE @query_verify   NVARCHAR(max)

   SET @query_backupTOAzBLOB = 'BACKUP DATABASE [' + @dbname + '] TO  URL =''' + @path + @dbname + '/' + @dbname + '_' + @date +'.bak'' 
                           WITH CREDENTIAL = ''' + @credential + ''',NOFORMAT, NOINIT,  NAME =''' + @dbname + ''',
                           NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10, CHECKSUM'
   EXEC (@query_backupTOAzBLOB)
   SET @query_verify = 'RESTORE VERIFYONLY  FROM URL =''' + @path + @dbname + '/' + @dbname + '_' + @date +'.bak'' 
                           WITH  CREDENTIAL = ''' + @credential + ''',  FILE = 1,  NOUNLOAD,  STATS = 5'
   EXEC(@query_verify)
   FETCH NEXT FROM db_cursor INTO @dbname   
END   
CLOSE db_cursor   
DEALLOCATE db_cursor

您的程式碼有兩個問題。

  1. 您的主要問題:使用非STATIC游標懸停sys.databases 可能會導致數據庫被跳過。
  2. 您有 SQL 注入漏洞。您可以使用 引用所有參數QUOTENAME,但BACKUP實際上無論如何都允許對所有參數進行參數化,因此您實際上可以BACKUP直接使用參數執行,不需要動態 SQL。
DECLARE @dbname sysname;
DECLARE @path nvarchar(120) = N'[my_storage_url]';
DECLARE @credential sysname = 'BackupStorageCredential';
DECLARE @date nvarchar(250) = CAST( GETDATE() AS Date );

DECLARE db_cursor CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR
SELECT name FROM sys.databases
WHERE name IN ('db1','db2','db3')
 AND state_desc = 'ONLINE';

OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO @dbname; 
WHILE @@FETCH_STATUS = 0   
BEGIN

   DECLARE @fullPath nvarchar(255) = @path + @dbname + '/' + @dbname + '_' + @date +'.bak';

   BACKUP DATABASE @dbname
   TO URL = @fullPath 
   WITH CREDENTIAL = @credential, NOFORMAT, NOINIT, NAME = @dbname,
       NOSKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10, CHECKSUM;

   RESTORE VERIFYONLY
   FROM URL = @fullPath
   WITH CREDENTIAL = @credential, FILE = 1, NOUNLOAD, STATS = 5;

   FETCH NEXT FROM db_cursor INTO @dbname; 
END;
CLOSE db_cursor; 
DEALLOCATE db_cursor;

您可能還應該考慮將時間附加到 URL,因為執行兩次將失敗。

引用自:https://dba.stackexchange.com/questions/305465