国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

開源組件之Greenplum數據庫故障處理分享

IT那活兒 / 3486人閱讀
開源組件之Greenplum數據庫故障處理分享

接到應用側反饋GP數據庫有些表經常出現突然無法查詢的情況,或者表的某些數據查詢不了了,并且報錯信息都非常相似,報錯信息均指向表對應的數據文件校驗不一致,報錯信息如下:

運行日志:【在Agent[1330162]執行結果:存儲過程:p_dw_ulc_usr_prov_happy_ds執行完成,返回信息:參數名稱:o_return_code參數值:XX000,參數名稱:o_return_msg參數值:SQL5:從接口取原始數據出錯!

錯誤信息:Block checksum does not match.  Expected 0xBD17CA1E and found 0x450D9B9 (cdbappendonlystorageread.c:1210)  …………………………Append-Only segment file/data1/primary/gpfs/gpseg186/33389/2435928/65966825.1537, block header offset in file = 50650432, bufferCount 2990,】


看到報錯信息,立馬想到是否是磁盤問題造成文件在寫磁盤的時候出現了問題,按照這個思路抓緊核查磁盤。






檢查磁盤:
1、檢查硬盤的狀態在位正常


2、硬盤錯誤統計次數為0


3、鏈路無誤碼

RAID卡底層日志沒有發現有reset、time out等異常打印


4、Message中也未有發現有IO的異常打印






綜述:未發現異常


暫時排除磁盤問題,那還有哪里出問題會導致數據問題?順其自然想到是否是GP數據庫在primary實例和mirror實例數據同步的時候出現問題?


我們先來溫故一下primary實例和mirror實例主備復制的機制。


大家都知道Greenplum 是基于PostgreSQL開發,PostgreSQL的主備也是通過流復制實現,但是Segment節點中的Primary和Mirror之間的數據同步是基于文件級別的同步方式實現的。為什么Primary和Mirror不能再使用流復制實現呢?

主要有兩個原因:

  • Append Only表不寫WAL日志,所以Append Only表的數據就不能通過XLOG發送到Mirror再Apply;

  • pg_control等文件也是不寫WAL日志,也只能通過文件方式同步到Mirror。


Primary和Mirror同步機制:

Primary和Mirror同步的內容主要有兩部分,即文件和數據。之所以Primary和Mirror要同步文件,是因為Primary和Mirror之間可以自動failover,只有兩者保持同步才能相互替代,如果只把數據同步過去,pg_control、pg_clog、pg_subtrans 沒有同步,那么從Primary切換到Mirror就會出現問題。


GP master和GP slave卻不用擔心這些問題,Append Only 表的數據只會存在 Segment,所以WAL日志足夠保持GP master和GP slave同步(只要是流復制,pg_control、pg_clog、pg_subtrans 這些文件Slave會自動更新,無需從Master同步)。


數據同步:

當GP master向Primary下發執行計劃后,Primary開始執行,如果是DML操作,那么Primary會產生XLOG及更新page。會在SlruPhysicalWritePage函數中(寫數據頁)產生FileRepOperationOpen、FileRepOperationWrite、FileRepOperationFlush、FileRepOperationClose等指令消息(消息中包含具體要更新的文件page及內容),通過primary sender進程向Mirror發送Message,然后Mirror的mirror consumer等進程解析消息,執行變更。XLOG通過XLogWrite函數(寫XLOG)執行同樣的操作,把XLOG更新同步過去。


文件同步:

Primary的recovery進程會循環把Primary的 pg_control、pg_clog、pg_subtrans 等文件覆蓋到Mirror。同時檢查XLOG是否一致,如果不一致以Primary為主,對Mirror進行覆蓋。除把Primary部分文件同步到Mirror之外recovery進程還會將Mirror上面的臨時文件刪掉。


根據以上的機制,在實驗環境做了兩個實驗進行驗證:




測試#1: Mirror無法寫入的情況:


步驟:

  • 1. 將mirror的data目錄設置為gpadmin無權限訪問。

  • 2. 在master上操作, 進行數據寫入。


結果:

  • 1. 寫入操作卡住一段時間(等待mirror寫入)。

  • 2. primary發現無法與mirror同步, 因此將mirror設置為down的狀態。

  • 3. 數據寫入繼續在primary進行, 寫入完成。


結論:

正常情況下, 一個事務必須在primary和mirror都寫入完成的情況下才會提交, 如果primary和mirror無法同步, 那么會在超時后將mirror標記為 down的狀態。


日志:

gpadmin=# insert into t1 select generate_series(1,100000) ;

WARNING:  mirror failure, could not complete mirrored request identifier pg_xlog/000000010000000000000001 ack state waiting for ack, failover requested  (seg0 172.28.8.2:23168 pid=20162)

HINT:  run gprecoverseg to re-establish mirror connectivity

CONTEXT:  mirroring role primary role mirroring state sync segment state in shutdown process name(pid) filerep uninitialized process(20162) filerep state not initialized

position ack begin 0x7f4a97f3e040 position ack end 0x7f4a97fbe040 position ack insert 0x7f4a97f69c58 position ack consume 0x7f4a97f69c58 position ack wraparound 0x7f4a97fbe040 insert count ack 43 consume count ack 44

WARNING:  mirror failure, could not complete operation on mirror, failover requested  (seg0 172.28.8.2:23168 pid=20162)

DETAIL:  identifier pg_xlog/000000010000000000000001 operation not specified relation type flat file message count -1

...

INSERT 0 100000

Time: 37849.733 ms




測試2: 模擬Primary寫入過程中數據損壞情況


步驟:

1. 在master進行寫入操作。

2. 在寫入的同時, 破壞primary的table文件. (cat xxx >> [table file]), 模擬硬件/文件系統問題導致損壞的情況。

3. 寫入完成后, 對表執行select操作。


結果:

1. 寫入可以正常完成, 因為寫入的操作的塊文件正常完成(fsync)。

2. 由于文件被破壞, 因此在select的時候會報錯。

3. 同時, 由于復制是基于塊的同步, 因此primary的損壞操作(人為追加)不會同步到mirror上, 因此mirror上的文件沒有問題。


結論:

1.當數據寫入時, 數據塊分兩條線走, 一條發送給mirror, 一條到primary落盤。

2.GP只會檢查數據塊本身是否寫入完成(fsync), 對于落盤之后的外部操作無法感知, 即硬件/系統問題引起的數據文件損壞在數據塊落盤后是無法發現的

3.只有在之后讀取到對應的數據文件時, 才會檢查到數據塊錯誤.

日志:

gpadmin=# insert into t1 select generate_series(1,100000000);

INSERT 0 100000000

Time: 44379.438 ms

gpadmin=# copy (select * from t1) to /dev/null;

WARNING:  page verification failed, calculated checksum 24539 but expected 27626  (seg0 slice1 172.28.8.2:23168 pid=22869)

ERROR:  invalid page in block 6129 of relation base/16384/16388  (seg0 slice1 172.28.8.2:23168 pid=22869)

gpadmin=# packet_write_wait: Connection to 10.152.9.3 port 22: Broken pipe

[gpadmin@sdw3 16384]$ md5sum 16388

83918050bc9ce93dfad130a24e105e61  16388

[gpadmin@sdw2 16384]$ md5sum 16388

48b7740a044bb3398283f4d44e01e46b  16388

## 切換到mirror后: ##

gpadmin=# copy (SELECT * from t1 ) to /dev/null;

COPY 100000000

Time: 36918.063 ms

gpadmin=#

通過上面的實驗可以了解到primary實例和mirror實例之間的同步機制:當數據寫入時候, 數據塊分兩條線走, 一條發送給mirror, 一條到primary落盤,GP只會檢查數據塊本身是否寫入完成(fsync), 對于落盤之后的外部操作無法感知, 即硬件/系統問題引起的數據文件損壞在數據塊落盤后是無法發現的,只有在之后讀取到對應的數據文件時, 才會檢查到數據塊錯誤。



上面實驗報錯明顯的指出了是primary實例下的文件有校驗不一致的情況發生,那我們接著往下看mirror的文件是否有問題。

這個該怎么驗證?很簡單,把出現問題的文件和對應mirror實例下的文件做個md5sum的校驗,看結果值是否一致,如一致則表明mirror實例下的文件肯定也損壞了,如不一致,則把兩個文件備份一份,再把mirror實例下的文件覆蓋primary實例下有問題的文件,對有問題的表再做一次查詢,看是否還報錯,通過實驗及測試,如果AO表使用上面的方法可以解決文件壞塊的問題,則說明是文件損壞的問題,不是在primary實例和mirror實例之間同步數據造成,因為如果是同步數據造成的,mirror文件也會損壞。


問題分析到這里遇到了瓶頸,磁盤也沒有問題,也不是數據庫數據同步造成的,那該是什么原因造成的呢?


看來只能對損壞的文件進行分析了,把之前報錯的文件全部收集出來對文件塊進行分析,


數據文件 7398846.1: Block 124473 checkusm 錯誤

- 日志顯示損壞位置為 block header offset in file = 644305640

- 通過解析該數據文件, 對應的block為 124473

- 數據文件顯示block 21406存在checksum錯誤, head中的checksum與實際不符

- 同時, Mirror的文件正常

***** Block 124473 Start ***( Position: 644305640) *************************

-----

HeaderKind: 1

Header Checksum Valid (checksum -1229617606)

(AoHeaderKind_SmallContent)

executorBlockKind: 1 rowCount: 67

headerLen: 24 uncompressedLen: 32302 compressedLen: 4421

firstRowNumber: 8904392

Content checksum doesnt match storedChecksum: 945093312, computedChecksum: 1985286725


數據文件 15165123.1: Block 21406 checksum 錯誤:

- 日志顯示損壞位置為 block header offset in file = 182856032

- 通過解析該數據文件, 對應的block為 21406

- 數據文件顯示block 21406存在checksum錯誤, head中的checksum與實際不符

- 同時, mirror的數據文件正常。

***** Block 21406 Start ***( Position: 182856032) *************************

-----

HeaderKind: 1

Header Checksum Valid (checksum 454188836)

(AoHeaderKind_SmallContent)

executorBlockKind: 1 rowCount: 270

headerLen: 24 uncompressedLen: 32716 compressedLen: 8298

firstRowNumber: 5759608

Content checksum valid (checksum: -482616586)


總結:

目前我們可以確定, 數據文件的確存在受損的問題, 且損壞只發生在primary segment上。


下面我們對出現文件損壞的表在進行分析下:

- 我們在深入檢查table文件之后, 發現primary并沒有缺損, 事實上primary從08ed2000位置開始被寫了"0"

- primary從08ed2000 到 08ee03e0 都是0, 而mirror并不是

- 同時, 16進制的08ed2000,08ee03e0分別對應10進制的149757952和149816288, 恰好都是是4096的整數倍(即這個位置是一個4096大小的block的開始)

2 < 08ed2000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

3 < *    << 這里的星號表示都是0

4 ---

5 > 08ed2000  4c 4b d6 af 07 f2 31 74  10 4b e7 f5 8f fc 77 f9  |LK....1t.K....w.|

6 > 08ed2010  1c 7e 02 39 49 16 21 3b  70 f4 39 52 f3 e5 df 8c  |.~.9I.!;p.9R....|

7 > 08ed2020  76 c4 99 ea bf af 73 8b  33 ae 76 38 d2 5f 15 a0  |v.....s.3.v8._..|

- 同樣另外一張表, primary的01110000開始到0111ecf0變成了0, 而mirror不是:

1 1118209,1118210c1118209,1122000

2 < 01110000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

3 < *

4 ---

5 > 01110000  cf 9c 87 4d 9e 61 d7 61  97 4f b0 5f 66 ff 84 fd  |...M.a.a.O._f...|

6 > 01110010  2b f6 ef d9 5f b0 b7 ed  bc 6b 47 ef 84 97 ac f0  |+..._....kG.....|

- 16進制01110000和0111ecf0分別對應10進制17891328和17951984, 同樣是4096的整數倍。


綜上所述, 經研發部門確認該問題并非GPDB造成, 因為GPDB從來不會對table文件寫0。所以將從軟硬件方面來繼續排查問題 (XFS? LVM? SAN? RAID card?)。


問題分析到這里基本可以得出結論,造成Block checksum does not match問題的不是磁盤,也不是數據庫軟件本身的問題,但是還需要從主機系統等層面進行分析,已聯系操作系統等相關廠商一起進行分析,后續有進展將繼續分享。


這個問題目前的處理方法很簡單,有兩種

1.找到該實例對應的mirror實例,在對應mirror實例下找到對應的數據文件,通過MD5SUM工具來校驗mirror和primary實例下數據文件的值是否一致,通過mirror的文件來覆蓋primary下的文件來解決;


2. 一般這種表都為歷史時間分區表,數據可以通過hadoop集群重新寫入,所以如果出現問題,則可以通過把該表刪除,并重新入數來解決;





greenplum 數據文件的追根溯源


上面的講到了GP數據庫中文件的損壞,及排查思路,那怎么確定損壞的數據文件和表之間的關系,下面在一起了解下這個關系如何確定;

首先介紹下在GP數據庫中表的存儲格式:Heap表和AO表(AORO表,AOCO表)

  • Heap表:這種存儲格式是從PostgreSQL繼承而來的,目前是GP默認的表存儲格式,只支持行存儲。

  • AO表:AO表最初設計是只支持append的(就是只能insert),因此全稱是Append-Only,在4.3之后進行了優化,目前已經可以update和delete了,全稱也改為Append-Optimized。AO支持行存儲(AORO)和列存儲(AOCO)。


從上面的這個錯誤信息可以看出表在primary實例對應的數據文件有損壞,遇到這個問題,首先想到的就是這個數據文件對應的是那個表,但是該如何通過數據文件查到對應的表呢?


熟悉GP數據庫的工程師立馬會想到通過pg_class 中的relfilenode 這個信息來找到對應的表例如:


這樣就找到了對應的表,大家肯定會說這也太簡單了,這種方式一般都是用來查heap表和一些剛好是AO表的數據文件對應的應用數據表。


但是GP數據庫中AO表是一種比較特殊的表,每個AO表都有一個關聯的系統表,該系統表用于管理文件系統上的段文件,所以我們可以查到下面兩種結果,仔細看這兩種結果有什么不同:


AO表的行存和列存在數據庫中存儲時名稱是有區別的,區別如下:

AORO(行存)表名:  [pg_aoseg.pg_aoseg_xxxxxx>]

AOCO(列存)表名:  [pg_aoseg.pg_aocsseg_xxxxxx>]


這明顯不是我們想要的表,遇到這種結果我們該怎么通過這個系統表來找到對應的表?


當年一些有經驗的老鳥曾告訴過一種比較偷懶的辦法是AO表的系統表結構中結尾都是數字結束的,這些數字就是該表所對應的relfilenode,我就試了下,結果如下:

還真的查到了,快捷方便,所以在接下來的一段時間里,我一直使用這種方式也解決了很多問題。


直到一次故障,讓我意識到偷懶的辦法只能用來偷懶,在遇到更棘手的故障時,這種純經驗式解決方法是行不通的。事情是這的,應用側反饋又出現了Block checksum does not match的報錯,把對應的數據文件號發給我后。按照老方法根據文件號,通過pg_class 中的relfilenode來找對應的表,找到后發現是張AO表,然后又根據AO表的系統表后面的數字找對應的表,結果這次沒找,確認了好幾次就是這個文件號,但是查出來的結果卻是為空;


結果如下:

這讓我意識到該辦法不科學不嚴謹,不能予以依賴,通過基于原理的辦法步驟來找對應的表。


首先想到AO表所有信息會存在pg_appendonly數據字典中,然后一步步按照流程來查詢,最終找到了的對應表;


在后續通過幾次實驗得出了一個兩張數據字典表的關聯關系:

  • ao表的系統表   pg_class 的oid等于pg_appendonly  的segrelid;

  • ao表的基表中  pg_class 的oid等于pg_appendonly 的relid


今天的GP故障分享就到這里,后續會繼續帶來現場各種問題處理的案例分享和心得體會,我們下次見。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/130221.html

相關文章

  • 探索Greenplum的實踐,了解新一代大數據處理利器

    摘要:上有主節點和從節點兩部分,兩者主要的功能是生成查詢計劃并派發,以及協調并行計算,同時在上保存著,這個全局目錄存著一組數據庫系統本身所具有的元數據的系統表。 前言:近年來,互聯網的快速發展積累了海量大數據,而在這些大數據的處理上,不同技術棧所具備的性能也有所不同,如何快速有效地處理這些龐大的數據倉,成為很多運營者為之苦惱的問題!隨著Greenplum的異軍突起,以往大數據倉庫所面臨的很多...

    supernavy 評論0 收藏0

發表評論

0條評論

IT那活兒

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<