?
?
《Replication的犄角旮旯》系列導(dǎo)讀
Replication的犄角旮旯(一)--變更訂閱端表名的應(yīng)用場景
Replication的犄角旮旯(二)--尋找訂閱端丟失的記錄
Replication的犄角旮旯(三)--聊聊@bitmap
Replication的犄角旮旯(四)--關(guān)于事務(wù)復(fù)制的監(jiān)控
Replication的犄角旮旯(五)--關(guān)于復(fù)制identity列
Replication的犄角旮旯(六)-- 一個DDL引發(fā)的血案(上)(如何近似估算DDL操作進度)
Replication的犄角旮旯(七)-- 一個DDL引發(fā)的血案(下)(聊聊logreader的延遲)
Replication的犄角旮旯(八)-- 訂閱與發(fā)布異構(gòu)的問題
Replication的犄角旮旯(九)-- sp_setsubscriptionxactseqno,賦予訂閱活力的工具
---------------------------------------華麗麗的分割線--------------------------------------------
?
前言: 這是昨天剛剛發(fā)生的案例,盡管事件的起因只是一個簡單的DDL操作,但影響面和影響時間可以說是大大超出了預(yù)期;我們將在描述本案例的前因后果之后,聊聊如何近似估算DDL的操作進度,以及關(guān)于logreader延遲的問題;
由于直接找MS開了case,直接引用標(biāo)準(zhǔn)回復(fù)格式;
?
=====================華麗麗的分割線========================
?
問題描述
=========
對于一張11億的數(shù)據(jù)進行PK字段的int到bigint的類型轉(zhuǎn)換,一直沒有完成。發(fā)現(xiàn)replication延遲僅1小時
?
問題排查
=========
1.sp_replcounters發(fā)現(xiàn)replbeginlsn的值一直沒有改變,但是replnextlsn一直在變化
2.sp_replcounters返回未發(fā)送的transaction持續(xù)上升
?
發(fā)生原因
=========
1. 執(zhí)行ALTER TABLE修改PK字段從INT到bigint時,由于一直沒有完成,這被視為是一個active transaction,這個值代表當(dāng)前LOG的minLSN, 由于這個transaction一直沒有做完,所以這個值一直沒有變化
|
Replbeginlsn |
binary(10) |
Log sequence number (LSN) of the current truncation point in the log. |
http://technet.microsoft.com/en-us/library/ms190486(v=SQL.110).aspx
?
2. 但是根據(jù)我們對于log reader的理解,這個beginLSN即使一直沒有變化,也不會影響log reader對于日志的讀取,因為log reader會直接從replnextlsn開始掃描
?
3. 由于active transaction一直沒有提交,導(dǎo)致日志無法被截斷,日志持續(xù)自增,目前已經(jīng)有270GB, 4000個VLF
?
4. VLF太多通常是會導(dǎo)致log reader讀取日志較慢,但是由于目前4000個VLF中只有2500個處于status=2的活動狀態(tài),并不是很多,這也不是導(dǎo)致replication延遲的原因
?
5.select *from fn_dblog(null,null)發(fā)現(xiàn)有大量的LOP_MODIFY_COLUMN的日志記錄 (處理在LCX_HEAP上),這個應(yīng)該針對于每一條記錄做類型轉(zhuǎn)換時都需要記錄的日志.而這個記錄還在不斷增多.由于這部分日志會有超過11億條,并且replication不需要發(fā)送這些日志(因為這張表已經(jīng)從article中移除).但是這部分日志還是需要被log reader掃描一遍,然后跳過去,這樣的掃描造成了log reader讀取日志變慢,從而導(dǎo)致replication的延遲.
?
解決方案
========
1.持續(xù)等待到ALTER TABLE做完,這樣log reader跳完了所有的日志以后,replication的延遲會自動追上去
2.手動cancel這個alter table,讓他回滾,這樣就不會產(chǎn)生新的日志,log reader不需要再掃描那些日志,也會慢慢追上延遲
?
最后您通過cancel這個alter table的語句,這個問題得以緩解.
?
下一步方案
========
根據(jù)我們以前case的歷史背景,和今天的電話溝通,我建議您對于這張表的字段修改還是使用導(dǎo)到新表,然后重命名的方式.因為這樣的辦法使用的是select into,屬于BULK操作,在SIMPLE模式下是不記日志的,所以不會對replication有影響.
?
=====================華麗麗的分割線========================
?
案例補充說明:
由于alter table操作并不能直接獲取操作的進度(sys.dm_exec_requests中的percent_complete對alter table操作不計算執(zhí)行進度),經(jīng)過MS工程師的指點,我們依然可以間接的估算出操作進度;以下通過一個測試案例說明
1、創(chuàng)建一個數(shù)據(jù)表,填充數(shù)據(jù);
test_1表,id列為主鍵自增列,類型bigint;填充數(shù)據(jù)51W條,數(shù)據(jù)大小2G左右;
2、修改id類型(int改為bigint),由于id是主鍵,所以需要先刪除主鍵約束才能繼續(xù)alter table。刪除主鍵約束后,手動checkpoint一下,清理一下fn_dblog;
3、執(zhí)行alter table語句并檢查fn_dblog
可以看到大量的修改行的記錄,完成alter table后再查一下fn_dblog,總記錄數(shù)51W多,基本與數(shù)據(jù)量一致;
4、按照下面的腳本篩選一下,可以看到,alter table操作(對堆表),實際是每行都急了一條modify的日志
SELECT
[
Current LSN
]
,Operation,Context,
[
Transaction ID
]
,
[
Log Record Fixed Length
]
,
[
Log Record Length
]
,
AllocUnitId
FROM
fn_dblog(
NULL
,
NULL
) fnlog
WHERE
Operation
=
'
LOP_MODIFY_ROW
'
AND
Context
=
'
LCX_HEAP
'
AND
[
Transaction ID
]
=
'
0000:00ed4660
'
然后我們在對Current LSN分析,看看跨了幾個VLF
形如:00028b3d:0000002f:001e
其中第一段00028b3d表示VLF號,于是將上述結(jié)果集中的Current LSN按第一段分組計數(shù),使用下面的腳本即可;
--
查詢fn_dblog中每個VLF包含的記錄數(shù)
SELECT
LEFT
(
[
Current LSN
]
,
CHARINDEX
(
'
:
'
,
[
Current LSN
]
)
-
1
),
COUNT
(
1
)
FROM
fn_dblog(
NULL
,
NULL
) fnlog
WHERE
Operation
=
'
LOP_MODIFY_ROW
'
AND
Context
=
'
LCX_HEAP
'
AND
[
Transaction ID
]
=
'
0000:00ed4660
'
GROUP
BY
LEFT
(
[
Current LSN
]
,
CHARINDEX
(
'
:
'
,
[
Current LSN
]
)
-
1
)
可以看到,目前查詢到的記錄中,平均每個VLF中包含1900左右的記錄數(shù)
4、先計算出按照平均1900/VLF,需要多少個VLF才能支持寫完51W條記錄(510000/1900,約為268個VLF)
5、結(jié)合DBCC LOGINFO,可以得出當(dāng)前活動VLF的數(shù)量(當(dāng)alter table執(zhí)行時,由于未提交或回滾,VLF處于活動狀態(tài)而不能被截斷),在比較預(yù)計VLF數(shù)和當(dāng)前活動的VLF,即可知道當(dāng)前alter table的進度
這里最好加一個限定,fn_dblog查出來的VLF號是16進制的,換成10進制是166717,再去DBCC LOGINFO的結(jié)果集查詢,增加 fseqno>=166717的條件;
小結(jié) :根據(jù)fn_dblog中某一段的日志情況(通過Operation='LOP_MODIFY_ROW' AND Context='LCX_HEAP' AND [Transaction ID]='0000:00ed4660'確認(rèn)正在執(zhí)行的DDL操作,其中[Transaction ID]和Current LSN的起始位置,可以通過dbcc opentran確定),統(tǒng)計出平均VLF中的記錄數(shù)(由于實際環(huán)境中影響日志記錄的因素較多,因此需要多看幾個VLF來估算DDL操作日志量的平均占比情況),再根據(jù)DBCC LOGINFO中當(dāng)前活動VLF的數(shù)量推算出DDL操作的進度;
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

