MySQL Q&A說說checksum table 有同學問到 checksum table在邏輯備份時候前後是否可以用於驗證數據一致性。擴展一下發現有一些有趣的問題,比如數據插入順序不同、表引擎不同、操作系統位數不同等。 www.2cto.com 插入順序不同是否有影響 我們知道全表掃描是可以有很多種順序的,尤其當表裡面出現過delete動作以後,邏輯導出再導入另外一個表後,兩個表的全表掃描結果可能不同。 Checksum table計算返回值的邏輯大致如下: Cpp代碼 ha_checksum crc= 0; foreach(row in table) { row_crc= get_crc(row); crc+= row_crc; } return crc; 可以看到只要總行數已經行內容相同,與讀取行的順序無關。 從這個邏輯還能得到一下幾個結論: www.2cto.com 1) 與使用的引擎無關,也就是說即使主備不用同一個引擎,checksum也可用於檢查。雖然InnoDB有隱藏行,但這裡無視。 2) 與是否有索引無關。row_crc只用行本身的數據來計算,並不包括索引數據。 也就是說如果能夠保證兩個表裡面的數據一樣,表結構(列內容和順序一樣),操作系統一樣,MySQL版本一致,是能夠保證checksum的結果的。 下面我們討論集中“不一樣” www.2cto.com 字段順序不同是否有影響 在個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即相同。