zoukankan      html  css  js  c++  java
  • checksum table 【转】

     

    来自:http://dinglin.iteye.com/blog/1791922

     

    有同学问到 checksum table在逻辑备份时候前后是否可以用于验证数据一致性。扩展一下发现有一些有趣的问题,比如数据插入顺序不同、表引擎不同、操作系统位数不同等。

    插入顺序不同是否有影响

     

    我们知道全表扫描是可以有很多种顺序的,尤其当表里面出现过delete动作以后,逻辑导出再导入另外一个表后,两个表的全表扫描结果可能不同。

    Checksum table计算返回值的逻辑大致如下:

    1. ha_checksum crc= 0;  
    2. foreach(row in table)  
    3. {  
    4.   row_crc= get_crc(row);  
    5.   crc+= row_crc;  
    6. }  
    7. return crc;  

    可以看到只要总行数已经行内容相同,与读取行的顺序无关

     从这个逻辑还能得到一下几个结论:

    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
    从上面计算每个fieldcrc上看,若为变长字段(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. ha_checksum crc= 0;  
    2. foreach(row in table)  
    3. {  
    4.   row_crc= get_crc(row);  
    5.   crc+= row_crc;  
    6. }  
    7. return crc;  

     可以看到只要总行数已经行内容相同,与读取行的顺序无关

     从这个逻辑还能得到一下几个结论:

    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

    从上面计算每个fieldcrc上看,若为变长字段(varchar),由于用于计算的是实际长度,因此不会影响。比如将表的varchar(20)字段改成varchar(25),不会改变checksum的值。

    但若将char(20)改成char(25),或者int改成bigint,则会改变checksum

     

    操作系统位数不同        

    因为返回值是unsigned long,我们就担心32位和64位机器的溢出问题。所幸在计算过程中的ha_myisam直接定义为uint32,只是在返回的时候才转成unsigned long,因此无影响。

     

    字符集不同        

    这个问题其实一直比较含糊。实际上与输入字符集有关。但有一个结论是肯定的:若表里面字段的unhex()值相同,得到的checksum即相同。

     
  • 相关阅读:
    git 在局域网新建远程库及本地开发常用命令
    sql server 常用操作
    LNMPA遇到504 Gateway time-out错误的解决方法
    安全cookie登录状态设计方案
    linux 启动ftp服务,sftp服务
    最详细的cookie和浏览隐私之间的关系
    IE无法获得cookie,ie不支持cookie的解决办法,火狐支持
    关于mysql联合索引
    常用Mysql命令
    常用Linux命令、包括vi 、svn
  • 原文地址:https://www.cnblogs.com/zhoujinyi/p/3224333.html
Copyright © 2011-2022 走看看