前言:數(shù)據(jù)庫越大,使用時(shí)間越長(zhǎng),貌似穩(wěn)定性也在逐步下降。數(shù)據(jù)頁邏輯錯(cuò)誤,可能是DBA遇到比較棘手的問題之一,本文將基于實(shí)戰(zhàn)模式給出一些檢查及處理的方法。當(dāng)然,任何方法都是受制于環(huán)境的限制,本文中介紹的方法也只適用于某些特定環(huán)境,僅供參考;
===================華麗麗的分割線========================
前幾天碰到一個(gè)錯(cuò)誤,具體信息如下:
SQL Server 檢測(cè)到基于一致性的邏輯 I/O 錯(cuò)誤 pageid 不正確(應(yīng)為 6:49413777,但實(shí)際為 0:0)。在文件 'M:/SQLDATA/Pk_4.ndf' 中、偏移量為 0x00005e3fd22000 的位置對(duì)數(shù)據(jù)庫 ID 5 中的頁 (6:49413777) 執(zhí)行 讀取 期間,發(fā)生了該錯(cuò)誤。SQL Server 錯(cuò)誤日志或系統(tǒng)事件日志
或許這是DBA遇到比較棘手的問題之一了。萬幸的是,發(fā)生錯(cuò)誤的數(shù)據(jù)庫是一個(gè)事務(wù)復(fù)制環(huán)境中的訂閱庫,而且有負(fù)載均衡扛著,基本上對(duì)業(yè)務(wù)沒有影響;
1、發(fā)現(xiàn)該錯(cuò)誤后,第一反應(yīng)是存儲(chǔ)(樓主的土豪公司用的是IO卡)出現(xiàn)邏輯錯(cuò)誤,嘗試手動(dòng)重啟服務(wù)器,讓IO卡進(jìn)行自檢;進(jìn)入系統(tǒng)后,發(fā)現(xiàn)問題沒有解決;
這一步,在IO卡自檢完成進(jìn)入系統(tǒng)后,需要進(jìn)一步使用廠商提供的監(jiān)控程序檢查IO卡是否有物理壞塊,并收集相關(guān)日志。經(jīng)過其他同事檢查,IO卡沒有異常報(bào)錯(cuò);
2、通過我們的監(jiān)控工具定位到publication是位于Publisher_A的pk_order_BEQ_new,該publication中涉及3個(gè)表
Order_A / Order_B / Order_C
3、在出現(xiàn)問題的機(jī)器上(以下稱為subscriber_A)通過select count(1) from table_name(nolock)的方式快速檢測(cè)具體是哪個(gè)表有問題;
此處的檢測(cè)方法有局限性,初步分析如下:
a) 如果是小表,可能在頁損壞之前有類似操作,導(dǎo)致全部頁還在緩存區(qū)中,因而select count(1)是可以獲取結(jié)果的,無法判斷出該表是否存頁損壞;
b) 如果IAM頁中還有6:49413777的信息,且該頁還在緩存區(qū)中,也是無法判斷出該表是否存頁損壞;
c) 如果IAM頁中沒有6:49413777的信息,則select count(1)的時(shí)候會(huì)跳過已損壞的頁,仍然可以獲取結(jié)果,也是無法判斷出該表是否存頁損壞;
只有當(dāng)IAM頁中有6:49413777的信息,而該頁又被交換出緩存區(qū),需要進(jìn)行物理讀的時(shí)候,才會(huì)導(dǎo)致select count(1)無法獲取結(jié)果,具體情況如下:
此處檢測(cè) Order_A正常,Order_B報(bào)錯(cuò);但這只能證明Order_B表確實(shí)存在損壞的頁,而Order_A卻不能斷定一定是正常的;
當(dāng)時(shí)的檢測(cè)辦法只是按照select count(1)的方式,判斷出Order_B表存在壞頁;但實(shí)際上,可以從Publisher_A的distribution.dbo.msrepl_errors中獲取當(dāng)前由復(fù)制引起的無法寫入損壞頁的XACT_Seqno,進(jìn)而通過sp_browsereplcmds ‘XACT_Seqno’,’ XACT_Seqno’,及command_id定位到具體引起該錯(cuò)誤的對(duì)象名、操作類型和主鍵值;
但此方法也有弊端,由于頁中可能存在多條記錄,如果是頁頭損壞,將導(dǎo)致該頁中的所有記錄都無法讀取,而msrepl_errors重試間隔大約1分鐘,所以通過此方法確定損壞的數(shù)據(jù)頁較慢;
4、通過distribution.dbo.msrepl_errors定位到orderexpend_pop表也存在損壞頁,并定位到是由delete操作發(fā)現(xiàn)異常,因此修改subscriber_A上相應(yīng)的復(fù)制存儲(chǔ)過程;
之前采用的僅屏蔽掉IF部分的做法在此處并不適用,因?yàn)閐elete時(shí)的返回信息并不再是“影響0行記錄”,而是由于頁損壞導(dǎo)致記錄無法找到并刪除;
delete [dbo].[Order_A]where [Id] = @pkc1--if @@rowcount = 0-- if @@microsoftversion>0x07320000-- exec sp_MSreplraiserror 20598
此處為了方便后面定位可能出現(xiàn)的損壞頁,修改存儲(chǔ)過程如下:
先創(chuàng)建記錄表monitor.dbo.tmp_byxl_Order_A_20140428
--CREATE TABLE monitor.dbo.tmp_byxl_Order_A_20140428 (id BIGINT,checkdate DATETIME DEFAULT GETDATE())--再修改存儲(chǔ)過
新聞熱點(diǎn)
疑難解答
圖片精選