原因不明的原木船減速
我有許多 SQL 2008 實例,它們都在執行 Microsoft SQL Server 2008 (SP4)(已
select @@VERSION
在相關伺服器上確認)。它們在 Windows Server 2008 或 Windows Server 2008 R2 上執行。其中兩個僅用於與 Red Gate SQL Backup 7.4.0.23 一起登錄,我遇到了其中一個問題。(它是 2008 R2 伺服器之一,如果有區別的話。)我正在使用一個 t-sql 作業,它滾動瀏覽很長的數據庫列表(從其他伺服器動態提取)並恢復它們。
以前,這項工作只需不到 10 分鐘。現在需要一個半小時到兩個半小時。沒有程式碼更改,也沒有大幅增加要恢復的數據庫數量。它的同級伺服器具有幾乎相同的程式碼,可以在 4 分鐘內執行此作業。(兄弟伺服器是非 R2 伺服器之一,如果這有所不同的話。)
事件日誌和 SQL 錯誤日誌顯示以下錯誤:
作業系統錯誤 0x80770006(未能檢索此錯誤的文本。原因:317)。
我不知道這是否是問題的原因;Google 建議當不同版本的 SQL Server 共存或 Red Gate SQL Backup 6.x 需要特殊更新檔時會發生這種情況。我認為這些都不是問題,因為錯誤是間歇性的,SQL Server 版本相同,並且我正在執行 Red Gate SQL Backup 7.x,但我肯定是錯的。Red Gate 論壇建議執行查詢以查看 VAS 記憶體是否不足,因為這可能會導致類似問題。
VAS Total avail mem, KB Max free size, KB 8320072080 8314974784
我嘗試解決的其他問題包括:
- 清除“C:\ProgramData\Red Gate\SQL Backup\Log”中的舊日誌文件$$ instancename $$",因為上次作業變慢是因為該目錄中的日誌文件太多。
- 檢查並解決伺服器上的任何記憶體問題。
- 確保防病毒軟體排除了 .sqb 文件(SQL 備份)。
CHKDSK
在涉及的捲上 執行。- 看著作業執行
sp_WhoIsActive
。- 檢查 msdb 以確保清除作業正常執行。最早的條目是四個星期大,但它似乎仍然過大。
DBCC CheckDB
在 msdb 上執行。- 要求那些對儲存實用程序有可見性的人檢查那裡的任何故障。他們說我的儲存是“最佳的”。
我打算做的事情:
- 將 msdb 的歷史清除為僅一周。這是一個阻塞查詢,所以我想等到幾個小時後,即使客戶沒有主動查詢這個實例。
看著作業執行
sp_whoisactive
似乎在 msdb 上顯示了很多PAGEIOLATCH
(SH
和EX
),但等待通常不到一秒。(查詢是更新備份集的過程。)我能找到的唯一錯誤是(來自 SQL 錯誤日誌)的間歇性變體:
2016-05-25 14:12:39.18 Backup Error: 3201, Severity: 16, State: 7. 2016-05-25 14:12:39.18 Backup Cannot open backup device 'SQLBACKUP_D99ABDE1-42E6-4617-B1EB-BDA30BF8113B'. Operating system error 0x80770006(failed to retrieve text for this error. Reason: 317).
(緊隨其後的是“日誌已恢復。”)和(來自事件查看器應用程序日誌):
SQLVDI: Loc=SVDS::Open. Desc=Bad State. ErrorCode=(-1). Process=8056. Thread=10512. Server. Instance=DR. VD=Global\SQLBACKUP_D99ABDE1-42E6-4617-B1EB-BDA30BF8113B_SQLVDIMemoryName_0. Cannot open backup device 'SQLBACKUP_D99ABDE1-42E6-4617-B1EB-BDA30BF8113B'. Operating system error 0x80770006(failed to retrieve text for this error. Reason: 317).
我錯過了什麼?我還能在哪裡看?
我下班後做的事情:
- 將 msdb 清除到一周。
- 為 Red Gate SQL 備份的 VDI 超時添加系統資料庫項。(我之前更改了這個值,然後刪除了該鍵。預設值為 30 秒,我認為一個數據庫似乎掛起的時間比 30 秒長得多,所以我輸入了一個具有預設值的鍵來確定。)
沒有區別,但我確實找到了這個查詢,它似乎給了我一個線索。特別是一個數據庫,我認為我
sp_WhoIsActive
花了很長時間才注意到它。這不是我的想像。大約恢復時間包括 5068100、4252443、4408026、2184080、2786363(除了 330、373 等之外)。(那是毫秒。)我檢查了這個數據庫中 VLF 的數量,只有 46 個,所以還有其他問題。我將載入完整的日誌傳送數據庫列表並再次執行它。
輔助數據庫處於恢復狀態,而不是待機狀態。我們使用 Red Gate 進行日誌傳送以進行壓縮,因為我們已經將加密備份的副本寫入該伺服器上的共享,並且擔心主伺服器上可能存在成本。有很多數據庫正在發貨。該伺服器上超過 800 個。我嘗試將其作為減少 msdb 爭用的一個過程。
這些機器是裸機,而不是虛擬機。據我所知,它只是落後了,爭論要麼是恢復,要麼是寫入有關恢復到 MSDB 的資訊(或兩者兼而有之)。最近的恢復是在最後一分鐘內。
我將所有正在運送的數據庫載入到此查詢中:
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 *, rn = ROW_NUMBER() OVER (PARTITION BY DatabaseName ORDER BY StartTime) INTO #blat FROM sys.fn_trace_gettable(@path, DEFAULT) WHERE DatabaseName IN ( N'db1', N'db2' -- , ... ) ORDER BY StartTime DESC; SELECT b.DatabaseName, b.TextData, ApproximateRestoreTime = DATEDIFF(MILLISECOND, b.StartTime, b2.StartTime) FROM #blat AS b LEFT OUTER JOIN #blat AS b2 ON b.DatabaseName = b2.DatabaseName AND b2.rn = b.rn + 1 WHERE b.EventClass = 115 AND b.EventSubClass = 2 ORDER BY b.StartTime DESC; GO DROP TABLE #blat;
(但我編輯它給我開始時間,就像一個健全的檢查。)這給了我一系列的結果,比如:
DatabaseName ApproximateRestoreTime StartTime DB1 2228166 5/26/16 12:07 PM DB1 370 5/26/16 12:07 PM DB1 373 5/26/16 12:07 PM DB1 366 5/26/16 12:07 PM DB1 383 5/26/16 12:07 PM DB1 350 5/26/16 12:07 PM DB1 350 5/26/16 12:07 PM DB1 1730 5/26/16 12:07 PM DB1 1726 5/26/16 12:07 PM DB1 426 5/26/16 12:07 PM DB1 1946 5/26/16 12:07 PM DB2 2237880 5/26/16 12:07 PM DB2 2420 5/26/16 12:07 PM DB2 2933 5/26/16 12:07 PM DB2 1723 5/26/16 12:07 PM DB2 360 5/26/16 12:07 PM DB2 353 5/26/16 12:07 PM DB2 1370 5/26/16 12:07 PM DB2 5433 5/26/16 12:07 PM DB2 400 5/26/16 12:07 PM DB2 436 5/26/16 12:07 PM DB2 856 5/26/16 12:07 PM DB3 2255540 5/26/16 12:07 PM DB3 2513 5/26/16 12:07 PM DB3 390 5/26/16 12:07 PM DB3 360 5/26/16 12:07 PM DB3 470 5/26/16 12:07 PM DB3 4830 5/26/16 12:07 PM DB3 1046 5/26/16 12:07 PM DB3 2753 5/26/16 12:06 PM DB3 373 5/26/16 12:06 PM DB3 933 5/26/16 12:06 PM DB3 813 5/26/16 12:06 PM DB4 2272020 5/26/16 12:06 PM DB4 2290 5/26/16 12:06 PM DB4 1936 5/26/16 12:06 PM DB4 353 5/26/16 12:06 PM DB4 353 5/26/16 12:06 PM DB4 360 5/26/16 12:06 PM DB4 393 5/26/16 12:06 PM DB4 4000 5/26/16 12:06 PM DB4 853 5/26/16 12:06 PM DB4 2133 5/26/16 12:06 PM DB4 346 5/26/16 12:06 PM
在我看來,數據庫恢復得很好,而減速是將此資訊寫入 msdb。
sp_WhoIsActive
這與顯示出很多緩慢的事實相結合:<?query -- (@param0 nvarchar(20), @param1 nvarchar(46), @param2 nvarchar(48), @param3 nvarchar(48), @param4 nvarchar(48), @param5 nvarchar(48), @param6 nvarchar(48), @param7 nvarchar(48), @param8 nvarchar(48), @param9 nvarchar(42), @param10 nvarchar(77), @param11 nvarchar(24), @param12 nvarchar(9), @param13 nvarchar(16), @param14 nvarchar(10), @param15 nvarchar(28), @param16 nvarchar(7), @param17 nvarchar(7), @param18 nvarchar(9), @param19 nvarchar(3), @param20 nvarchar(24), @param21 nvarchar(13), @param22 nvarchar(3), @param23 nvarchar(27), @param24 nvarchar(9), @param25 nvarchar(24), @param26 nvarchar(3), @param27 nvarchar(27)) declare @backup_set_id int declare @restore_history_id int select @backup_set_id = backup_set_id from msdb.dbo.backupset where backup_set_uuid = N'{4A3BE7C3-AF68-40D8-9261-35C781B6642C}' if @backup_set_id is null begin declare @media_set_id int declare @media_count int select @media_set_id = media_set_id from msdb.dbo.backupmediaset where media_uuid = N'{D603F5E0-6150-476A-A5B1-E7D2840AB05C}' (etc., etc.)
讓我覺得是的,msdb 是我的問題。
截至今天早上,它只有一周的歷史記錄,但每 15 分鐘有 800 多個數據庫被恢復,所以 MDF 仍然是 5 GB。我禁用了這些工作並將這個數字減少到 3 天並添加了一些索引。這項工作現在需要 4 或 5 分鐘。
我仍然不確定為什麼一個執行了兩年多的系統,令人高興的是,有四個星期的歷史現在只執行了三天,但我懷疑我的儲存團隊錯了,我的儲存不是最佳的。我已經讓他們對此進行評估。
同時,如果此實例的其中一台伺服器正在保護藍屏,我不會過時兩個半小時!
託管服務提供商現在說這
C:
是碎片化的。無論如何,我已經將 msdb 移動到更快的儲存空間,因為它是系統上最難工作的數據庫。
這比評論要大,但要先測試然後再實施:
您正在對 800 多個數據庫進行日誌傳送。那就是您每 15 分鐘登錄一次的大量數據庫。
您應該將一些數據庫解除安裝到另一台伺服器。恕我直言,單個伺服器上的 800 個數據庫很多!
當我們將 200 多個數據庫從 NY 發送到 LD 地區時,我們遇到了類似的日誌發送問題。
我們所做的如下:
- 有阻塞寫入
msdb.dbo.sysjobhistory with (TABLOCKX)
。TABLOCK
提示意味著對 sysjobhistory 的訪問始終是序列化的。而且由於您每 15 分鐘執行大量作業,因此會出現爭用(阻塞)。- 我們實現了跟踪標誌 TF – 1236。它將引入數據庫鎖分區。對 DATABASE 鎖進行分區可以使鎖列表的深度在每個本地分區中易於管理。這顯著優化了用於獲取 DATABASE 鎖的訪問路徑。
sysjobhistory
在和log_shipping_monitor_history_detail
表上創建索引,如下所示:use msdb go create nonclustered index [nc_DBA_sysjobhistory] on dbo.sysjobhistory ( ,[job_id] ,[step_id] ,[run_date] ) include ( [instance_id] ,[step_name] ,[sql_message_id] ,[sql_severity] ,[message] ,[run_status] ,[run_time] ,[run_duration] ,[retries_attempted] ,[server] ) go use [msdb] go ----- this will help sys.sp_MSprocesslogshippingretentioncleanup proc (delete from msdb.dbo.log_shipping_monitor_history_detail).. that does the cleanup of logshipping. create nonclustered index [nc_DBA_LogShipping_monitor_history_detail] on [dbo].[log_shipping_monitor_history_detail] ( [agent_id] asc ,[agent_type] asc ,[log_time_utc] asc ) go