【sql server日志傳送】SqlServer事務日志傳送(不停機不在主庫加共享文件版本)【log shipping最佳實踐】


SqlServer事務日志傳送(不停機不在主庫加共享文件版本)

                                    Auth:chaoqun.guo 2020-07-27

【0】需求

前提

(1)不能停機、重啟服務、現在沒有加入域

(2)現在已經有一個鏡像副本了

現有業務,想做一個從庫,有什么好辦法?

 

我遇到的問題:

  1. alwayon(需要加入域 所以要重啟不行)
  2. 鏡像(因為有一個鏡像副本了不能多個鏡像副本),
  3. 日志傳送(延遲時間太長了且需要UNC路徑權限似乎也需要修改啟動賬戶需要重啟服務)
  4. 發布訂閱(很多業務老表沒有主鍵)

最終,我選擇了日志傳送,深入研究后,解決了UNC訪問路徑共享文件夾的問題,以及相關主庫開共享文件夾不安全等問題。

 

【1】基本原理與前置要求

【1.1】基本原理

  1. 以全備在從庫初始化之后,主庫備份事務日志(增量備份)到指定文件夾A
  2. 從庫從文件夾A復制事務日志備份到本地文件夾B
  3. 從庫從B文件夾對事務日志進行還原

測試環境我們的策略如下:

我們的測試數據操作到底要多久從庫才能同步上去呢?

  1. 每分鍾復制一次,每分鍾生成1個trn文件。
  2. 每5分鍾同步一次新的trn文件到從庫上的文件夾上去。
  3. 從庫每分鍾按生成順序還原1個trn文件

從上面3個規律,我們可以發現,核心時間花費是在文件備份和文件傳輸上。

假設備份需要3秒,傳輸需要10秒,那么我們的平均時間是

5分+3秒+10秒+1分鍾 =6分13秒

(這一分鍾是可能文件傳過來之前正好運行了一次還原操作,導致錯過需要再等下一次周期,周期是一分鍾)

 

【1.2】前置要求

  1. 版本要求:sql server2005及以上,主數據庫為完整恢復/大容量日志恢復模式
  2. .netframework 3.5 環境
  3. 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. 每分鍾復制一次,每分鍾生成1個trn文件。
  2. 每5分鍾同步一次新的trn文件到從庫上的文件夾上去。
  3. 從庫每分鍾按生成順序還原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
    

 

 

各種共享以及復制訪問等情況是否會有問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM