SqlServer事務日志傳送(不停機不在主庫加共享文件版本)
Auth:chaoqun.guo 2020-07-27
【0】需求
前提
(1)不能停機、重啟服務、現在沒有加入域
(2)現在已經有一個鏡像副本了
現有業務,想做一個從庫,有什么好辦法?
我遇到的問題:
-
alwayon(需要加入域 所以要重啟不行)
-
鏡像(因為有一個鏡像副本了不能多個鏡像副本),
-
日志傳送(延遲時間太長了且需要UNC路徑權限似乎也需要修改啟動賬戶需要重啟服務)
-
發布訂閱(很多業務老表沒有主鍵)
最終,我選擇了日志傳送,深入研究后,解決了UNC訪問路徑共享文件夾的問題,以及相關主庫開共享文件夾不安全等問題。
【1】基本原理與前置要求
【1.1】基本原理
-
以全備在從庫初始化之后,主庫備份事務日志(增量備份)到指定文件夾A
-
從庫從文件夾A復制事務日志備份到本地文件夾B
-
從庫從B文件夾對事務日志進行還原
測試環境我們的策略如下:
我們的測試數據操作到底要多久從庫才能同步上去呢?
-
每分鍾復制一次,每分鍾生成1個trn文件。
-
每5分鍾同步一次新的trn文件到從庫上的文件夾上去。
-
從庫每分鍾按生成順序還原1個trn文件
從上面3個規律,我們可以發現,核心時間花費是在文件備份和文件傳輸上。
假設備份需要3秒,傳輸需要10秒,那么我們的平均時間是
5分+3秒+10秒+1分鍾 =6分13秒
(這一分鍾是可能文件傳過來之前正好運行了一次還原操作,導致錯過需要再等下一次周期,周期是一分鍾)
【1.2】前置要求
-
版本要求:sql server2005及以上,主數據庫為完整恢復/大容量日志恢復模式
-
.netframework 3.5 環境
-
Sql server代理服務必須開啟
【1.3】測試架構分布
主庫:
IP/URL |
角色 |
描述 |
10.20.50.23 |
主服務器 |
日志傳送主服務器 |
test |
主庫 |
日志傳送主庫 |
D:\temp_bak |
備份文件夾(本地) |
主庫日志文件備份 |
D:\dba_tools |
DBA工具文件夾(本地) |
復制事務備份到從庫 |
從庫:
IP/URL |
角色 |
描述 |
10.20.50.42 |
從庫 |
日志傳送從庫 |
test |
同名從庫 |
日志傳送同名從庫 |
d:\copy_file |
備份文件夾(共享) |
接收主庫備份文件並還原 |
【1.4】軟件包示例
sxs.rar這個軟件包哪里來的?這個就是操作系統鏡像(最好是與當前windows server版本相同或相近可兼容的iso鏡像文件)文件里面的一個叫sxs文件夾。
新建call.vbs調用copy_tran_bakfile.bat
copy_tran_bakfile.bat
@echo off for /l %%i in (1,1,6) do ( dir z: 1>nul if errorlevel 1 (net use z: \\10.20.50.42\log_shipping\2433_18 $GTRwxhi@A6f#!wQ /user:log_shipping) echo %date%%time% >>e:\dba_tools\output.log echo %date%%time% >>e:\dba_tools\error.log replace /a E:\log_shipping_tran\* z:\ >>e:\dba_tools\output.log 2>>e:\dba_tools\error.log timeout /T 55 /NOBREAK )
call.vbs
set ws=WScript.CreateObject("WScript.Shell") ws.Run "e:\dba_tools\copy_file.bat",0
到時候定時任務可以用call.vbs,這樣調用bat的黑窗就不會彈出
【1.5】最佳實踐基本步驟
(1)兩台機器均為:windows server2012R2+sql server2016
(2)主庫機器:10.20.50.23 從庫機器:10.20.50.42
(3)現在是做 sql server主從(利用備份還原的方式)
主從實現操作:
(1)主庫備份到本地一個目錄 : D:\temp_bak
(2)從庫新建了一個共享目錄: d:\copy_file
對 administrator/administrators/log_shipping/Users 賬戶共享,
其中 log_shipping 是新建的所屬 Users組的普通windows用戶,它和 Users 都給了只讀權限。
(3)在主庫上,新建了一個 windows計划任務。使用administrators用戶作為啟動用戶
定時復制 主庫上 D:\temp_bak 文件夾中的文件到 從庫的 D:\log_shipping\ 文件夾。
(4)從庫sql server代理使用log_shipping啟動。
定時還原 從庫共享文件夾 D:\log_shipping\ 中的備份文件
【2】環境與前置工作准備
【2.1】主從庫安裝.netframework 3.5
(1)服務器管理器,添加角色與功能
(2)全部下一步下一步,直至功能選擇,勾上.Net FrameWork3.5
然后直接下一步下一步完事,但有時候會報錯,如下:
(3)這個時候我們重新來一次,指定備用源
然后找到我們傳過來文件的這個目錄:
輸入進去,然后點擊確定即可。
然后點擊安裝,等待安裝完成
【2.2】主庫:新建 D:\temp_bak備份文件夾
【2.3】主庫:新建 D:\dba_tools文件夾
並把文件 copy_tran_bakfile.bat復制進去,文件見【1.4】軟件包
【2.4】從庫:新建 D:\copy_file 備份接收文件夾
(1)這個需要開共享,且需要給everyone 讀取權限,也可以給sql server代理啟動賬戶以讀取權限,強烈推薦后者
(2)比如代理的 log_shipping 輸入進去,然后點擊添加,給只讀權限即可。(然后這個賬戶所在用戶組也需要添加進來,比如Users)
(3)或者新建一個賬戶,然后用這個賬戶啟動從庫代理,然后共享文件夾只給這個賬戶訪問即可(注意,修改代理啟動賬戶需要重啟代理)
不過反正是新的從庫,重啟代理服務也是沒有關系的。
如果共享成功請直接到【3】
如果共享失敗請檢查:
(1)共享功能
(2)共享程序
【3】sql server事務傳送
【3.1】構造測試主庫 test
--構造測試主庫 test
create database test;
go
--在test庫構造3個測試表 test1/test2/test3
select 1 as id into test..test1;
select 2 as id into test..test2;
select 3 as id into test..test3;
【3.2】利用 test 全備初始化從庫
(1)全量備份
--全量備份
backup database test to disk='D:\temp_bak\test.bak' with stats=10
(2)復制備份文件到從庫
--復制主庫test.bak文件到從庫,這里隨便找個文件夾即可,比如我選的就是D:\temp\ 目錄
--以norecovery 的方式還原到從庫,為避免主從位置不同,必須以move參數來指定還原數據庫的文件存放位置
restore database test from disk='D:\temp\test.bak' with norecovery,replace
,move 'test' to 'D:\Program Files\MSSQL1\MSSQL13.MSSQLSERVER\MSSQL\DATA\test.mdf'
,move 'test_log' to 'D:\Program Files\MSSQL1\MSSQL13.MSSQLSERVER\MSSQL\DATA\test_log.ldf'
(3)核驗
右擊數據庫=》刷新,如果出現了test數據庫,並且是正在還原的情況,那么就成功了
(4)刪除bak文件
操作完之后,為了保證安全,刪除主庫、從庫上的test.bak文件,
【3.3】(主庫)配置事務日志傳送
(1)在主庫:右擊test數據庫=》屬性=》事務日志傳送
把將此數據庫啟用為事務日志傳送配置中的主數據庫
(2)事務日志備份設置
我們設置備份目錄為實現預設創建好的 d:\temp_bak
(3)事務日志備份計划設置
這里因為是測試我們設置1分鍾備份一次,到這里設置好之后,一路確定確定下去就好了。
確定,成功
(4)核驗
核驗一:作業
我們可以看到我們操作完成后,生成了2個作業
LSBackup_test 以及 LSAlert_WIN-MMFDQB29HJK,前者是備份作業,后者是報警作業,我們只需要查看備份作業是否存在就好了。
我們來看一下作業是否執行成功,是否是按我們設置的一分鍾一次的頻率在執行
看一下歷史記錄,真的是一分鍾一次執行,且都執行成功了。
核驗二:查看備份文件是否生成在我們指定的目錄下
如下圖,已經生成了,證明我們主庫配置好了。
(5)暫時禁用 LSBackup_test 作業
為什么要暫時禁用這個作業呢,因為我們現在還沒配置 復制備份到從庫,也沒有配置在從庫還原,如果備份太多會導致從庫落后比較多。
等我們全部都配置好了,再開啟。
右擊 LSBackup_test 作業=》禁用
【3.4】(從庫)配置事務日志傳送
(1)在主庫:右擊test庫=》屬性=》事務日志傳送,點擊添加
(2)復制數據庫設置=》連接
點擊連接=》然后登錄連接從庫驗證
(3)輔助數據庫設置=》初始化
我們之前已經手動初始化了,這里我們選擇否,輔助數據庫已經初始化
(4)輔助數據庫設置=》復制文件
點擊復制文件選項卡,然后復制文件的目標文件夾填寫我們之前預設好的
點擊計划=》我們設置和備份一樣的頻率,一分鍾還原一次
(5)輔助數據庫設置=》還原事務日志
我們設置備用模式,備用模式可以讓我們在非還原時間點,從庫可以查詢使用,還原計划間隔我們設置成1分鍾一次,和備份、拷貝一樣。
一路點擊確定=》保存配置信息成功
(6)核驗
核驗一:作業
我們可以看到,從庫產生了三個作業,如下圖,前面三個作業就是
LSAlert_WIN-6BA1LAPNHHK:告警作業,我們用不上,忽略
LSCopy_WIN-MMFDQB29HJK_test:復制作業,因為本文我們是不停服操作,這個暫時沒用上,所以避免浪費資源禁用。
我們下個步驟會在主庫使用windows計划任務復制備份
LSRestore_WIN-MMFDQB29HJK_test:恢復作業,對指定文件夾中的事務日志備份進行順序恢復。
如果有文件則它會還原,如果沒有文件它有判定機制不做操作,但作業也會執行成功。
只有當發生還原實際錯誤的時候,或權限等訪問錯誤的時候作業才會失敗。
核驗二:數據核驗
這個整個都沒弄好,見后面整天弄完了才能看到
【3.5】(主庫)配置windows計划任務復制數據庫
(0)計划任務腳本內容
<1> copy unc(不推薦)
Rem 使用直接復制方式(不建議使用,因為如果主從沒有相同的windows賬戶和密碼,則無法免密直接訪問UNC) echo %date%%time% 1>>output.log replace /a d:\temp_bak\* \\10.20.50.42\copy_file >>d:\dba_tools\output.log 2>>d:\dba_tools\error.log
<2> net use (推薦)
Rem 使用net use方式(建議使用,只需要擁有從庫賬戶權限即可) @echo off for /l %%i in (1,1,6) do ( dir z:|find /c "trn" if errorlevel 1 (net use z: \\10.20.50.42\log_shipping\1433_17 $GTRwxhi@A6f#!wQ /user:log_shipping) echo %date%%time% >>e:\dba_tools\output.log echo %date%%time% >>e:\dba_tools\error.log replace /a E:\log_shipping_tran\* z:\ >>e:\dba_tools\output.log 2>>e:\dba_tools\error.log timeout /T 55 /NOBREAK )
注意,如果目錄、IP不同,腳本需要修改
(1)開始=》運行=》control schedtasks
打開任務計划程序
(2)創建任務
(3)創建任務=》常規
這里要使用管理員賬戶,由於我這里沒有實際管理員密碼,暫時先用這個管理組角色測試
正式服務器上,如果使用管理員賬戶+密碼,請選中下面的【不管用戶是否登錄都要運行】
(4)創建任務=》觸發器
我們新建一個觸發器,然后設置策略為每天執行一次,一次運行持續一天,且每5分鍾執行一次該任務中的操作。
(5)創建任務=》操作
把我們的腳本路徑輸入進去。
(6)創建任務=》條件
這個無需怎么修改,注意一下電源那里的復選框即可
(7)創建任務=》設置
好,到現在都配置好了,我們點擊確定。
(8)核驗
右擊=》運行
然后我們可以去我們的腳本所在目錄看日志,如下圖,沒有錯誤信息且輸出日志中告訴了我們添加了日志
這就算運行成功了,但還需實際核驗文件到底有沒有傳輸過去
登上從庫10.20.50.42 ,我們發現,已經傳到這個目錄上來了。
【4】最終同步核驗
【4.1】當前作業、計划、等情況
主庫:
IP/URL/名稱 |
角色 |
描述 |
10.20.50.23 |
主庫服務器 |
日志傳送主庫 |
test |
主庫 |
日志傳送主庫 |
D:\temp_bak |
備份文件夾(本地) |
主庫日志文件備份 |
D:\dba_tools |
DBA工具文件夾(本地) |
復制事務備份到從庫 |
Copy_tranBak_file |
Windows計划任務 |
調用bat復制備份文件到從庫 |
LSBackup_test |
數據庫作業 |
test庫事務日志備份/1分鍾1次,備份到d:\temp_bak |
從庫:
IP/URL |
角色 |
描述 |
|
10.20.50.42 |
從庫 |
日志傳送從庫 |
|
test |
同名從庫 |
日志傳送同名從庫 |
|
d:\copy_file |
備份文件夾(共享) |
接收主庫備份文件並還原 |
|
LSRestore_WIN-MMFDQB29HJK_test |
數據庫作業 |
用來還原trn備份到從庫test庫,並以備用模式存在,使得非還原操作時間,從庫可以只讀訪問 |
【4.2】啟動作業、計划任務
之前我們停了 主庫的LSBackup_test,主庫所在服務器的計划任務 copy_tranBak_file
我們現在都啟動起來
【4.3】構造測試數據
在主庫上執行:
select getdate()
select 4 as id into test..test4
select 5 as id into test..test5
select 6 as id into test..test6
目前時間是:2020-07-27 15:23:56.253
【4.4】同步時間分析
我們的測試數據操作到底要多久從庫才能同步上去呢?
-
每分鍾復制一次,每分鍾生成1個trn文件。
-
每5分鍾同步一次新的trn文件到從庫上的文件夾上去。
-
從庫每分鍾按生成順序還原1個trn文件
從上面3個規律,我們可以發現,核心時間花費是在文件備份和文件傳輸上。
假設備份需要3秒,傳輸需要10秒,那么我們的平均時間是
5分+3秒+10秒+1分鍾(這一分鍾是可能文件傳過來之前正好運行了一次還原操作,導致錯過需要再等一秒)
【4.5】查看同步情況
我等了5分多種(沒有實時一直等候),查看數據,表已經同步過去了。
到此,大功告成
【4.6】把主庫賬戶配置到從庫,避免孤立用戶
SELECT 'CREATE LOGIN [' + p.name + '] ' + CASE WHEN p.type IN ( 'U', 'G' ) THEN 'FROM windows ' ELSE '' END + 'WITH ' + CASE WHEN p.type = 'S' THEN 'password = ' + master.sys.fn_varbintohexstr(l.password_hash) + ' hashed, ' + 'sid = ' + master.sys.fn_varbintohexstr(l.sid) + ', check_expiration = ' + CASE WHEN l.is_expiration_checked > 0 THEN 'ON, ' ELSE 'OFF, ' END + 'check_policy = ' + CASE WHEN l.is_policy_checked > 0 THEN 'ON, ' ELSE 'OFF, ' END + CASE WHEN l.credential_id > 0 THEN 'credential = ' + c.name + ', ' ELSE '' END ELSE '' END + 'default_database = ' + p.default_database_name + CASE WHEN LEN(p.default_language_name) > 0 THEN ', default_language = ' + p.default_language_name ELSE '' END FROM sys.server_principals p LEFT JOIN sys.sql_logins l ON p.principal_id = l.principal_id LEFT JOIN sys.credentials c ON l.credential_id = c.credential_id WHERE p.type IN ( 'S', 'U', 'G' ) AND p.name NOT IN ( 'sa') AND p.name NOT LIKE '%##%' AND p.name NOT LIKE '%NT SERVICE%' AND p.name NOT LIKE '%NT AUTHORITY%'
【5】相關DMV、SP、系統表
日志傳送相關表和存儲過程
主服務器表
表 |
描述 |
log_shipping_monitor_alert |
存儲警報作業 ID。 僅當尚未配置遠程監視服務器時,主服務器上才會使用此表。 |
log_shipping_monitor_error_detail |
存儲與此主服務器關聯的日志傳送作業的錯誤詳細信息。 |
log_shipping_monitor_history_detail |
存儲與此主服務器關聯的日志傳送作業的歷史記錄詳細信息。 |
log_shipping_monitor_primary |
存儲一條此主數據庫的監視記錄。 |
log_shipping_primary_databases |
包含指定服務器上主數據庫的配置信息。 每個主數據庫存儲一行。 |
log_shipping_primary_secondaries |
將主數據庫映射到輔助數據庫。 |
主服務器存儲過程
存儲過程 |
描述 |
sp_add_log_shipping_primary_database |
設置日志傳送配置(包括備份作業、本地監視記錄及遠程監視記錄)的主數據庫。 |
sp_add_log_shipping_primary_secondary |
向現有的主數據庫添加輔助數據庫名稱。 |
sp_change_log_shipping_primary_database |
更改主數據庫設置,包括本地和遠程監視記錄。 |
sp_cleanup_log_shipping_history |
根據保持期清除本地歷史記錄及監視器上的歷史記錄。 |
sp_delete_log_shipping_primary_database |
刪除主數據庫的日志傳送,包括備份作業以及本地和遠程歷史記錄。 |
sp_delete_log_shipping_primary_secondary |
從主數據庫中刪除輔助數據庫名稱。 |
sp_help_log_shipping_primary_database |
檢索主數據庫設置並顯示 log_shipping_primary_databases 和 log_shipping_monitor_primary 表中的值。 |
sp_help_log_shipping_primary_secondary |
檢索主數據庫的輔助數據庫名稱。 |
sp_refresh_log_shipping_monitor |
利用指定的日志傳送代理的最新信息刷新監視器。 |
輔助服務器表
表 |
描述 |
log_shipping_monitor_alert |
存儲警報作業 ID。 僅當尚未配置遠程監視服務器時,輔助服務器上才會使用此表。 |
log_shipping_monitor_error_detail |
存儲與此輔助服務器關聯的日志傳送作業的錯誤詳細信息。 |
log_shipping_monitor_history_detail |
存儲與此輔助服務器關聯的日志傳送作業的歷史記錄詳細信息。 |
log_shipping_monitor_secondary |
存儲與此輔助服務器關聯的輔助數據庫監視記錄。每個輔助數據庫存儲一條監視記錄。 |
log_shipping_secondary |
包含指定服務器上輔助數據庫的配置信息。 每個輔助 ID 存儲一行。 |
log_shipping_secondary_databases |
存儲指定輔助數據庫的配置信息。 每個輔助數據庫存儲一行。 |
備注
與指定主數據庫位於同一個輔助服務器上的輔助數據庫共享 log_shipping_secondary 表中的設置。 如果一個輔助數據庫更改了共享設置,所有輔助數據庫的設置都將更改。
輔助服務器存儲過程
存儲過程 |
描述 |
sp_add_log_shipping_secondary_database |
設置用於日志傳送的輔助數據庫。 |
sp_add_log_shipping_secondary_primary |
為指定的主數據庫設置主服務器信息,添加本地和遠程監視器鏈接,並在輔助服務器上創建復制作業和還原作業。 |
sp_change_log_shipping_secondary_database |
更改輔助數據庫設置,包括本地和遠程監視記錄。 |
sp_change_log_shipping_secondary_primary |
更改輔助數據庫設置,例如源目錄、目標目錄和文件保持期。 |
sp_cleanup_log_shipping_history |
根據保持期清除本地歷史記錄及監視器上的歷史記錄。 |
sp_delete_log_shipping_secondary_database |
刪除輔助數據庫、本地歷史記錄和遠程歷史記錄。 |
sp_delete_log_shipping_secondary_primary |
從輔助服務器上刪除有關指定的主服務器的信息。 |
sp_help_log_shipping_secondary_database |
從 log_shipping_secondary、 log_shipping_secondary_databases和 log_shipping_monitor_secondary 表中檢索輔助數據庫設置。 |
sp_help_log_shipping_secondary_primary |
此存儲過程將在輔助服務器上檢索給定的主數據庫的設置。 |
sp_refresh_log_shipping_monitor |
利用指定的日志傳送代理的最新信息刷新監視器。 |
監視服務器表
表 |
描述 |
log_shipping_monitor_alert |
存儲警報作業 ID。 |
log_shipping_monitor_error_detail |
存儲日志傳送作業的錯誤詳細信息。 |
log_shipping_monitor_history_detail |
存儲日志傳送作業的歷史記錄詳細信息。 |
log_shipping_monitor_primary |
存儲與此監視服務器關聯的主數據庫的監視記錄。每個主數據庫存儲一條監視記錄。 |
log_shipping_monitor_secondary |
存儲與此監視服務器關聯的輔助數據庫的監視記錄。每個輔助數據庫存儲一條監視記錄。 |
監視服務器存儲過程
存儲過程 |
描述 |
sp_add_log_shipping_alert_job |
如果尚未創建日志傳送警報作業,則創建它。 |
sp_delete_log_shipping_alert_job |
如果沒有關聯的主數據庫,則刪除日志傳送警報作業。 |
sp_help_log_shipping_alert_job |
返回警報作業的作業 ID。 |
sp_help_log_shipping_monitor_primary |
從 log_shipping_monitor_primary 表中返回指定的主數據庫的監視記錄。 |
sp_help_log_shipping_monitor_secondary |
從 log_shipping_monitor_secondary 表中返回指定的輔助數據庫的監視記錄。 |
【6】使用郵件服務監控(從庫)
【6.1】配置郵件服務器
use msdb go if exists( select 1 from sys.databases where name = 'msdb' and is_broker_enabled=0 ) begin ALTER DATABASE msdb SET NEW_BROKER WITH ROLLBACK IMMEDIATE; alter database msdb set enable_broker; end --1.啟用Database Mail擴展存儲過程 go sp_configure 'show advanced options', 1 GO RECONFIGURE GO sp_configure 'Database Mail XPs', 1 GO RECONFIGURE GO sp_configure 'show advanced options', 0 GO RECONFIGURE GO exec msdb..sysmail_add_account_sp @account_name = 'dba_guochaoqun' --郵件帳戶名稱SQL Server內使用 ,@email_address = '815202984@qq.com' --發件人郵件地址 ,@display_name = '[10.20.50.42]' --發郵件出去后顯示的名稱 ,@mailserver_name = 'smtp@qq.com' --郵件服務器地址 ,@mailserver_type = 'SMTP' --郵件協議SQL 2005只支持SMTP ,@port = 25 --郵件服務器端口 ,@username = '81502984@qq.com' --用戶名 ,@password = 'a123456!' --密碼 --3.添加profile exec msdb..sysmail_add_profile_sp @profile_name = 'dba_profile'-- profile 名稱 ,@description = 'dba mail profile'-- profile 描述 ,@profile_id = null --4.映射account和profile exec msdb..sysmail_add_profileaccount_sp @profile_name = 'dba_profile'-- profile 名稱 ,@account_name = 'dba_guochaoqun'-- account 名稱 ,@sequence_number = 1-- account 在profile中順序
【6.2】監控腳本,監控還原錯誤=》發送表內容到郵件
use master; declare @tableHTML nvarchar(max),@title varchar(2000),@monitor_name varchar(1000),@top_num int set @title='[10.20.50.42] log_shipping error' set @monitor_name='log_shipping' set @top_num=10 if object_id('dba_monitor_count') is null create table dba_monitor_count(monitor_name varchar(1000),monitor_count int,record_time datetime) if exists( select top(30) * from msdb..log_shipping_monitor_error_detail where datediff(minute,log_time,getdate())<10 ) and not exists(select 1 from master..dba_monitor_count where monitor_name=@monitor_name and monitor_count>@top_num and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120) ) begin set @tableHTML = N'<H1>'+@title+'</H1>' +N'<div>' + N'<table border="1">' + N'<tr>' + N'<th> db_name </th>' + N'<th> ________log_time_______ </th>' + N'<th>message</th></tr>' + CAST( ( select top(30) td=isnull(database_name,' '),'', td=convert(varchar(100),log_time,20),'', td=message,'' from msdb..log_shipping_monitor_error_detail order by log_time for xml path('tr') ) as nvarchar(max) ) +'</table>' --print @tablehtml EXEC msdb..sp_send_dbmail @profile_name = 'dba_profile', @recipients = '815202984@qq.com;', @subject = @title, @body=@tablehtml, @body_format='HTML'; if @@error=0 begin if not exists(select 1 from master..dba_monitor_count where monitor_name=@monitor_name and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120)) insert into master..dba_monitor_count values(@monitor_name,1,getdate()) else update dba_monitor_count set monitor_count=monitor_count+1 where monitor_name=@monitor_name and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120) end end
【6.3】監控數據5分鍾未同步情況
利用LSN查詢,查看5分鍾前和5分鍾后的LSN是否相同,相同則證明沒有還原操作,未同步;
use master; declare @tableHTML nvarchar(max),@title varchar(2000),@monitor_name varchar(1000),@top_num int declare @before_LSN varchar(400),@now_LSN varchar(400) declare @before_time datetime,@now_time datetime,@table_name varchar(100) if object_id('dba_monitor_count') is null create table master..dba_monitor_count(monitor_name varchar(1000),monitor_count int,record_time datetime,error_flag int) set @title='數據庫備機[10.20.50.42] log_shipping 5 minutes not sync' set @monitor_name='data_not_sync' set @top_num=10 use asdegame; select @before_LSN=max([Current LSN]),@before_time=getdate() FROM ::fn_dblog(NULL,null) use master; waitfor delay '00:04:30' use asdegame; select @now_LSN=max([Current LSN]),@now_time=getdate() FROM ::fn_dblog(NULL,null) use master; set @tableHTML = N'<H1>'+@title+'</H1>' +N'<div>' + N'<table border="1">' + N'<tr>' + N'<th> ______record_time______ </th>' + N'<th> LSN </th></tr>' + CAST( ( select td=convert(varchar(100),record_time,20),'', td=LSN,'' from ( select @before_time as record_time,@before_LSN as LSN union all select @now_time as record_time,@now_LSN as LSN ) t for xml path('tr') ) as nvarchar(max) ) +'</table>' --print @tablehtml if @before_LSN=@now_LSN begin --如果連續報警次數沒超過 @top_num 次數 則發報警郵件,否則啥也不干 if not exists( select 1 from master..dba_monitor_count where monitor_name=@monitor_name and monitor_count>=@top_num and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120) ) begin EXEC msdb..sp_send_dbmail @profile_name = 'dba_profile', @recipients = 'guochaoqun@bianfeng.com;815202984@qq.com;fuxiaoping@bianfeng.com', @subject = @title, @body=@tablehtml, @body_format='HTML'; if @@error=0 begin if not exists(select 1 from master..dba_monitor_count where monitor_name=@monitor_name and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120) ) insert into master..dba_monitor_count values(@monitor_name,1,getdate(),1) else update dba_monitor_count set monitor_count=monitor_count+1,error_flag=1 where monitor_name=@monitor_name and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120) end end end --如果前面一直是失敗,失敗后的第一次成功 發送郵件 else begin --如果上一次郵件發送的是錯誤信息 if exists( select 1 from master..dba_monitor_count where monitor_name=@monitor_name and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120) and error_flag=1 ) begin --則發送已經正常的成功報告 set @tableHTML=replace(@tableHTML,@title,@title+'......is OK!') set @title=@title+'......is OK!' EXEC msdb..sp_send_dbmail @profile_name = 'dba_profile', @recipients = 'guochaoqun@bianfeng.com;815202984@qq.com;', @subject = @title, @body=@tablehtml, @body_format='HTML'; --修改error_flag,0為正常,1為錯誤報告,並且最大報錯次充值 if @@error=0 begin update master..dba_monitor_count set error_flag=0,monitor_count=0 where monitor_name=@monitor_name and convert(varchar(10),record_time,120)=convert(varchar(10),getdate(),120) end end end
各種共享以及復制訪問等情況是否會有問題。