首页 > Linux配置管理工具 > pt-table-checksum/sync的算法问题

pt-table-checksum/sync的算法问题

2014年10月21日

pt-table-checksum/sync的算法问题

http://blog.chinaunix.net/uid-16844903-id-3480621.html

在用pt-table-sync做数据一致性同步测试的时候,发现一个:数据不一样,校验值一样”的问题.

pt-table-sync选择的算法为chunk.(在groupby,stream算法下,不会出现该问题)

 

1       环境说明

表结构

CREATE TABLE `t2` (

`a` int(11) NOT NULL AUTO_INCREMENT,

`b` varchar(20) DEFAULT NULL,

PRIMARY KEY (`a`),

UNIQUE KEY `uniq_b` (`b`)

) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

 

主库,端口3306,数据如下

+—+——+

| a | b    |

+—+——+

| 2 | 1    |

| 1 | 2    |

| 3 | 3    |

+—+——+

从库,端口3307,数据如下

+—+——+

| a | b    |

+—+——+

| 1 | 1    |

| 2 | 2    |

| 3 | 3    |

+—+——+

 

主要的校验部分为.

COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`)))) AS UNSIGNED)), 10, 16)), 0)

各函数说明

函数名 功能 类别
ISNULL(expr) 若表达式expr的值是NULL,则返回1;否则返回0. 比较函数
CONCAT(str1, str2, …) 返回一个由自身所有参数合并而成的字符串.只要有一个参数是NULL,则返回NULL. 字符串函数
CONCAT_WS(delim, str1, str2, …) 与CONCAT类似,返回值为由第二个及后续输入参数合并在一起而得到的一个字符串,各输入参数之间用字符串deliim分隔.如果delim是NULL,则返回NULL;但参加合并的字符串里的NULL值和空字符串都将被忽略. 字符串函数
CRC32(str) 返回值为字符串str的循环冗余校验值,这个返回值是一个32位的无符号整数值.如果输入参数NULL值,则返回NULL 数值函数
CAST(expr AS type) 把表达式expr的值转换给定的类型. 类型转换函数
BIT_XOR(expr) 返回涉及选定行中的所有非NULL值的expr的按位异或值.如果都为NULL值,则返回0. 汇总函数
CONV(n, from_base, to_base) 返回值:把以from_base为底的数值n转换为以to_base为底,并把转换结果表示为一个字符串.只要参数中有NULL值,就返回NULL.参数from_base和to_base必须是一个2到36之间的整数.n将被看做是一个BIGINT整数值,不能为字符串. 字符串函数
LOWER(str) 返回把字符串str里的字符全部转换为小写字母后得到的一个字符串.如果str是NULL,则返回NULL 字符串函数
COALESCE(expr1, expr2, …) 返回值:输出参数中的第一个非NULL元素.如果所有元素全部是NULL,则返回NULL. 字符串函数

 

2       bug分析

 

注意:

从按位异或函数开始出现问题.不同的三列值,执行BIT_XOR()后的值相同了.

 

主库的函数拆分执行情况.

16:43:34 127.0.0.1:3306 test>select  CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`))) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+——-+

| crc   |

+——-+

| 1#2#0 |

| 2#1#0 |

| 3#3#0 |

+——-+

3 rows in set (0.00 sec)

 

16:43:45 127.0.0.1:3306 test>select  CRC32(CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`)))) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+————+

| crc        |

+————+

| 1467683016 |

|  312333377 |

|  746138015 |

+————+

3 rows in set (0.00 sec)

 

16:44:22 127.0.0.1:3306 test>select  CAST(CRC32(CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`)))) AS UNSIGNED) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+————+

| crc        |

+————+

| 1467683016 |

|  312333377 |

|  746138015 |

+————+

3 rows in set (0.00 sec)

 

16:45:10 127.0.0.1:3306 test>select  BIT_XOR(CAST(CRC32(CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`)))) AS UNSIGNED)) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+————+

| crc        |

+————+

| 1772088598 |

+————+

1 row in set (0.00 sec)

从库的函数拆分执行情况

16:43:09 127.0.0.1:3307 test>select  CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`))) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+——-+

| crc   |

+——-+

| 1#1#0 |

| 2#2#0 |

| 3#3#0 |

+——-+

3 rows in set (0.00 sec)

 

16:43:48 127.0.0.1:3307 test>select  CRC32(CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`)))) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+————+

| crc        |

+————+

| 1430105745 |

|  282815000 |

|  746138015 |

+————+

3 rows in set (0.00 sec)

 

16:44:15 127.0.0.1:3307 test>select  CAST(CRC32(CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`)))) AS UNSIGNED) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+————+

| crc        |

+————+

| 1430105745 |

|  282815000 |

|  746138015 |

+————+

3 rows in set (0.00 sec)

 

16:44:58 127.0.0.1:3307 test>select  BIT_XOR(CAST(CRC32(CONCAT_WS(‘#’, `a`, `b`, CONCAT(ISNULL(`b`)))) AS UNSIGNED)) AS crc FROM `test`.`t2` FORCE INDEX (`PRIMARY`) WHERE (1=1) FOR UPDATE;

+————+

| crc        |

+————+

| 1772088598 |

+————+

1 row in set (0.00 sec)

 

3       解决办法:暂无

本文的评论功能被关闭了.