checksum table 【转】
?
來自:http://dinglin.iteye.com/blog/1791922
?
有同學問到 checksum table在邏輯備份時候前后是否可以用于驗證數據一致性。擴展一下發現有一些有趣的問題,比如數據插入順序不同、表引擎不同、操作系統位數不同等。
插入順序不同是否有影響
?
我們知道全表掃描是可以有很多種順序的,尤其當表里面出現過delete動作以后,邏輯導出再導入另外一個表后,兩個表的全表掃描結果可能不同。
Checksum table計算返回值的邏輯大致如下:
可以看到只要總行數已經行內容相同,與讀取行的順序無關。
?從這個邏輯還能得到一下幾個結論:
1) 與使用的引擎無關,也就是說即使主備不用同一個引擎,checksum也可用于檢查。雖然InnoDB有隱藏行,但這里無視。
2) 與是否有索引無關。row_crc只用行本身的數據來計算,并不包括索引數據。
也就是說如果能夠保證兩個表里面的數據一樣,表結構(列內容和順序一樣),操作系統一樣,MySQL版本一致,是能夠保證checksum的結果的。
下面我們討論集中“不一樣”
字段順序不同是否有影響
在個row計算row_crc時,是每個字段依次計算的。但計算過程中會將上一個字段的結果作為計算下一個值的輸入。
| ????????????? switch (f->type()) { ??????????????? case MYSQL_TYPE_BLOB: ??????????????? case MYSQL_TYPE_VARCHAR: ??????????????? case MYSQL_TYPE_GEOMETRY: ??????????????? case MYSQL_TYPE_BIT: ???? ???????????{??? ????????????????? String tmp; ????????????????? f->val_str(&tmp); ????????????????? row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), ?????????????????????????? tmp.length()); ????????????????? break; ??????????????? }??? ?????????????? ?default: ????????????????? row_crc= my_checksum(row_crc, f->ptr, f->pack_length()); ????????????????? break; ????????????? }??? |
因此字段順序會影響結果。
字段長度不同是否有影響
即使看到相同的內容,也有可能得到不同的checksum。
從上面計算每個field的crc上看,若為變長字段(varchar等),由于用于計算的是實際長度,因此不會影響。比如將表的varchar(20)字段改成varchar(25),不會改變checksum的值。
但若將char(20)改成char(25),或者int改成bigint,則會改變checksum。
操作系統位數不同
因為返回值是unsigned long,我們就擔心32位和64位機器的溢出問題。所幸在計算過程中的ha_myisam直接定義為uint32,只是在返回的時候才轉成unsigned long,因此無影響。
字符集不同
這個問題其實一直比較含糊。實際上與輸入字符集有關。但有一個結論是肯定的:若表里面字段的unhex()值相同,得到的checksum即相同。
?
有同學問到 checksum table在邏輯備份時候前后是否可以用于驗證數據一致性。擴展一下發現有一些有趣的問題,比如數據插入順序不同、表引擎不同、操作系統位數不同等。
插入順序不同是否有影響
我們知道全表掃描是可以有很多種順序的,尤其當表里面出現過delete動作以后,邏輯導出再導入另外一個表后,兩個表的全表掃描結果可能不同。
Checksum table計算返回值的邏輯大致如下:
?可以看到只要總行數已經行內容相同,與讀取行的順序無關。
?從這個邏輯還能得到一下幾個結論:
1)?????? 與使用的引擎無關,也就是說即使主備不用同一個引擎,checksum也可用于檢查。雖然InnoDB有隱藏行,但這里無視。
2)?????? 與是否有索引無關。row_crc只用行本身的數據來計算,并不包括索引數據。
也就是說如果能夠保證兩個表里面的數據一樣,表結構(列內容和順序一樣),操作系統一樣,MySQL版本一致,是能夠保證checksum的結果的。
?
下面我們討論集中“不一樣”
?
字段順序不同是否有影響
在個row計算row_crc時,是每個字段依次計算的。但計算過程中會將上一個字段的結果作為計算下一個值的輸入。
?
| ????????????? switch (f->type()) { ??????????????? case MYSQL_TYPE_BLOB: ??????????????? case MYSQL_TYPE_VARCHAR: ??????????????? case MYSQL_TYPE_GEOMETRY: ??????????????? case MYSQL_TYPE_BIT: ???? ???????????{??? ????????????????? String tmp; ????????????????? f->val_str(&tmp); ????????????????? row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), ?????????????????????????? tmp.length()); ????????????????? break; ??????????????? }??? ?????????????? ?default: ????????????????? row_crc= my_checksum(row_crc, f->ptr, f->pack_length()); ????????????????? break; ????????????? }??? |
因此字段順序會影響結果。
?
字段長度不同是否有影響
即使看到相同的內容,也有可能得到不同的checksum。
從上面計算每個field的crc上看,若為變長字段(varchar等),由于用于計算的是實際長度,因此不會影響。比如將表的varchar(20)字段改成varchar(25),不會改變checksum的值。
但若將char(20)改成char(25),或者int改成bigint,則會改變checksum。
?
操作系統位數不同????????
因為返回值是unsigned long,我們就擔心32位和64位機器的溢出問題。所幸在計算過程中的ha_myisam直接定義為uint32,只是在返回的時候才轉成unsigned long,因此無影響。
?
字符集不同????????
這個問題其實一直比較含糊。實際上與輸入字符集有關。但有一個結論是肯定的:若表里面字段的unhex()值相同,得到的checksum即相同。
總結
以上是生活随笔為你收集整理的checksum table 【转】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用幻灯片做完整的“一站到底”抢答器
- 下一篇: 博客园我来了