藉助擴展事件查看SQL 2016備份和還原操做的內幕

當遇到備份或者還原操做佔用較長時間時,不少人會問:sql

  1. 備份/還原是否是僵死了?要不要kill掉,再重來?
  2. 究竟是哪個部分的操做佔用較長時間?
  3. 到底如今進行到什麼階段了

在SQL 2016 以前,要回答這些問題會比較困難一些,或者藉助某些不受支持的方式。SQL 2016開始引入了新擴展事件 backup_restore_progress_trace 來跟蹤備份和還原操做。咱們可使用它們來觀察備份和還原的更詳細的信息。數據庫

備份

先建立一個XE Session觀察備份:session

CREATE EVENT SESSION [xe_backup] ON SERVER 
ADD EVENT sqlserver.backup_restore_progress_trace(
    ACTION(
        sqlos.task_time,sqlserver.database_id,sqlserver.database_name,
        sqlserver.nt_username,sqlserver.session_id,sqlserver.session_nt_username,
        sqlserver.sql_text,sqlserver.username
    )
    )
ADD TARGET package0.event_file(SET filename=N'C:\Joe\xe\xeBackup.xel')
WITH (STARTUP_STATE=ON)
GO
ALTER EVENT SESSION [xe_backup] ON SERVER 
STATE=START;
GO

完成備份後,再來分析咱們捕獲的信息:sqlserver

BACKUP DATABASE [AdventureWorks2016CTP3] TO  DISK = N'C:\SQL2016\MSSQL13.MSSQLSERVER\MSSQL\Backup\aw.bak' 
WITH NOFORMAT, INIT,  NAME = N'AdventureWorks2016CTP3-Full Database Backup', 
SKIP, NOREWIND, NOUNLOAD, COMPRESSION,  STATS = 10
GO
ALTER EVENT SESSION [xe_backup] ON SERVER 
STATE=STOP;
GO
;WITH xevent AS (  
SELECT timestamp,operation_type,database_name,trace_level,trace_message,event_sequence  
FROM   (   
SELECT     timestamp  = xevent.value(N'(event/@timestamp)[1]', N'datetime2'),    
operation_type  = xevent.value(N'(event/data[@name="operation_type"]/text)[1]', N'nvarchar(32)'),    
database_name  = xevent.value(N'(event/data[@name="database_name"])[1]', N'nvarchar(128)'),    
trace_message = xevent.value(N'(event/data[@name="trace_message"])[1]', N'nvarchar(max)'),    
trace_level = xevent.value(N'(event/data[@name="trace_level"])[1]', N'nvarchar(max)'), 
event_sequence  = xevent.value(N'(event/action[@name="event_sequence"])[1]', N'int')   
FROM    (    SELECT xevent = CONVERT(XML, event_data)      
             FROM sys.fn_xe_file_target_read_file(N'c:\joe\xe\xeBackup_*.xel', NULL, NULL, NULL)   )
         AS y  
    ) AS xevent )

SELECT   database_name,timestamp,trace_level,trace_message,   
Duration = COALESCE( DATEDIFF(MILLISECOND, xevent.timestamp,LEAD(xevent.timestamp, 1) OVER(ORDER BY event_sequence)),0)
FROM xevent
ORDER BY event_sequence;

我這裏的查詢結果總共56行,highlight部分主要操做的信息。Duration列表示此操做全部時間。rest

由結果能夠看到備份的trace_level分爲Information of major steps in the operation和Verbose I/O related information,前者表示備份操做的中的主要步驟,後者表示某個步驟IO詳細狀況:code

由這些信息,咱們可以知道此備份操做主要的步驟有哪些,哪些步驟最耗時間orm

還原

還原我用的是上一個備份生成的文件,而且使用了REPLACE。server

CREATE EVENT SESSION [xe_restore] ON SERVER 
ADD EVENT sqlserver.backup_restore_progress_trace(
    ACTION(package0.event_sequence,sqlos.task_time,sqlserver.database_id,sqlserver.database_name,
    sqlserver.nt_username,sqlserver.server_instance_name,sqlserver.session_id,sqlserver.sql_text))
ADD TARGET package0.event_file(SET filename=N'C:\Joe\xe\xeRestore.xel')
WITH (STARTUP_STATE=ON)
GO

ALTER EVENT SESSION [xe_restore] ON SERVER 
STATE=START
GO
USE [master]
RESTORE DATABASE [AdventureWorks2016CTP3] FROM  DISK = N'C:\SQL2016\MSSQL13.MSSQLSERVER\MSSQL\Backup\aw.bak' 
WITH  FILE = 1,  NOUNLOAD, REPLACE,  STATS = 5
GO

觀察XE的數據:blog

ALTER EVENT SESSION [xe_restore] ON SERVER 
STATE=STOP
GO
;WITH xevent AS (  
SELECT timestamp,operation_type,database_name,trace_level,trace_message,event_sequence  
FROM   (   
SELECT     timestamp  = xevent.value(N'(event/@timestamp)[1]', N'datetime2'),    
operation_type  = xevent.value(N'(event/data[@name="operation_type"]/text)[1]', N'nvarchar(32)'),    
database_name  = xevent.value(N'(event/data[@name="database_name"])[1]', N'nvarchar(128)'),    
trace_message = xevent.value(N'(event/data[@name="trace_message"])[1]', N'nvarchar(max)'),    
trace_level = xevent.value(N'(event/data[@name="trace_level"])[1]', N'nvarchar(max)'), 
event_sequence  = xevent.value(N'(event/action[@name="event_sequence"])[1]', N'int')   
FROM    (    SELECT xevent = CONVERT(XML, event_data)      
             FROM sys.fn_xe_file_target_read_file(N'c:\joe\xe\xeRestore_*.xel', NULL, NULL, NULL)   )
         AS y  
    ) AS xevent )

SELECT   database_name,timestamp,trace_level,trace_message,   
Duration = COALESCE( DATEDIFF(MILLISECOND, xevent.timestamp,LEAD(xevent.timestamp, 1) OVER(ORDER BY event_sequence)),0)
FROM xevent
ORDER BY event_sequence;



經過以上信息,咱們可以知道還原數據庫時的主要操有哪些,哪些步驟比較耗時事件

現實狀況中數據庫還原,roll-forward以後應該還有一個undo(roll-back)操做來撤消未提交事務的修改。

總結

  1. 雖然是SQL 2016才引入這個新的XE事件,可是在其它版本上,理論是相通的,只是一些細節的差異。
  2. 本文使用的是一個小的示例庫,現實中生產庫的狀況要複雜一些。
  3. XE是一大利器,能夠幫咱們驗證不少理論細節。
相關文章
相關標籤/搜索