Sql-Server
從 SQL Server 2016 備份到 Azure URL 時備份文件失去
我有一個這樣的作業腳本,它應該使用儲存密鑰憑據將 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
您的程式碼有兩個問題。
- 您的主要問題:使用非
STATIC
游標懸停sys.databases
可能會導致數據庫被跳過。- 您有 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,因為執行兩次將失敗。