1.1、工作原理

pt-table-checksum会对校验的表数据进行数据块(数据块大小根据服务负载情况调整)划分,并对数据块数据进行checksun处理;存储在建立的表中。
在主库中执行基于statemnet的sql语句,生成数据块的checksum;在从库执行相同的sql语句,获取到数据块的checksum和主库的checksum进行比较。

1.2、执行过程

1. master设置binlog格式为语句。/ *!50108 SET @@ binlog_format:='STATEMENT'* /
2. master设置RR的隔离级别。RR具有静态数据,因此不需要锁定。SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READREAD<
3. master计算块数据校验和。checksums table:
Use REPLACE INTO select to set this_cnt, this_crc (传递给从属设备,实际上是为每个SLAVE设置cnt,crc).
该算法来自:COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(主键)AS UNSIGNED)),10,16)),0)
4.Slave 当同步完成时,开始运行REPLACE INTO select and set cnt,crc for each chunk of the slave 。
5.master checksums table:更新master_cnt,master_crc。这是为master的每个块设置cnt,crc。
6.slave 当同步完成时,开始运行update master_cnt,master_crc并为master的每个块设置cnt,crc。
接下来,我们只需要在校验和表中找到master_cnt <> this_cnt或OR master_crc <> this_crc记录。

dns是个特殊的方式;服务器连接参数不是自动发现,而是通过一个保存DSNs信息的表中获取。DSN方式指定table方式为dsn=h=host,D=percona,t=dsns

库中写入以下库和表:

CREATE TABLE percona.`dsns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`dsn` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
); insert into percona.dsns select 1,1,'h=127.0.0.1,u=rt,p=cc.123,P=18601'; insert into percona.dsns select 2,2,'h=127.0.0.1,u=rt,p=cc.123,P=18602';

  

测试数据:

18601和18602,是一个实例下配置的多端口主从
--mysql8.0测试
pt-table-checksum --nocheck-binlog-format --replicate=percona.checksums --recursion-method=dsn=h=10.0.0.1,D=td1,t=dsns --set-vars innodb_lock_wait_timeout=120 -urt -pcc.123 -h10.0.0.1 -P18601 --databases=test --quiet --判断到底哪个从库和主库数据不一致
pt-table-checksum --nocheck-binlog-format --replicate=percona.checksums --recursion-method=dsn=h=10.0.0.1,D=td1,t=dsns --set-vars innodb_lock_wait_timeout=120 -urt -pcc.123 -h10.0.0.1 -P18601 --databases=test --replicate-check-only --UAT测试
pt-table-checksum --nocheck-binlog-format --nocheck-replication-filters --replicate=percona.checksums --recursion-method=dsn=h=10.0.0.1,D=percona,t=dsns --set-vars innodb_lock_wait_timeout=120 -urt -pcc.123 -h10.0.0.1 -P18601 --databases=alid --quiets说明

ERRORS :检查时候发生错误和警告的数量。 DIFFS :0表示一致,1表示不一致。当指定--no-replicate-check时,会一直为0,当指定--replicate-check-only会显示不同的信息。 ROWS :表的行数。 CHUNKS :被划分到表中的块的数目。 SKIPPED :由于错误或警告或过大,则跳过块的数目。 TIME :执行的时间。 TABLE :被检查的表名。

说明:

1,加上参数–replicate-check-only,只显示有差异的结果,就可以显示出所有从库的差异,

结果会显示:Differences on VM_27_211_centos, 不同来自哪个机器,这里如果单实例,多端口,没法显示哪个端口从库。

2,指定--quiet时只输出errors,warnings和主从数据存在不一致的相关信息(在表非常多时该选项很有用)

3,--no-check-binlog-format 不对binlog的格式进行检查

4,--replicate= :把checksum的信息写入到指定表中,建议直接写到被检查的数据库当中。

5,--databases=,-d:要检查的数据库,逗号分隔。 --databases-regex 正则匹配要检测的数据库,--ignore-databases[-regex]忽略检查的库。Filter选项。

6,--tables=,-t:要检查的表,逗号分隔。如果要检查的表分布在不同的db中,可以用--tables=dbname1.table1,dbnamd2.table2的形式。

 修复数据:   

--修复从库数据18602是从库实例
--打印修复数据
pt-table-sync --replicate=percona.checksums --sync-to-master h=10.0.0.1,P=18602,u=rt,p=cc.123 --databases=test --print --执行
pt-table-sync --replicate=percona.checksums --sync-to-master h=10.0.0.1,P=18602,u=rt,p=cc.123 --databases=test --execute

 原理:

pt-table-checksum用来检测主从数据库上的数据一致性,其原理是通过在主库上运行一系列的MySQL函数计算每个表的散列值,并利用主从关系将相同的操作在从服务器上重放(基于statement格式的binlog),从而获取到主从服务器上的散列值然后比较散列值判定主从数据是否一致。

对于表中的单行数据,先检查每一列的数据类型,然后将所有的数据类型转换为字符串,再使用concat_ws()函数进行连接,然后根据连接后得到的字符串计算出checksum的值,默认的checksum算法为crc32。

对于数据量较大的表,如果单次计算整表的checksum值,会导致主库性能压力和主从延迟,因此会根据chunk_size和chunk_time等参数来对表进行拆分为多个chunk,计算chunk时,将该chunk中所有行的数据拼接起来进行checksum计算。

对比原理

在开始checksum计算时,会先修改会话级别binlog_format为STATEMENT和开启重复读隔离级别,使得主库上进行的计算SQL操作在从库上重放(不是值)

1,/*!50108 SET @@binlog_format := 'STATEMENT'*/

2,SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ

修改隔离级别,通过加锁保证在取数据行数(replaceinto select  from)到计算出检验值这段时间数据不会被修改。他采用块,来减少每次锁住数据的行数,这样提高了并发性

然后对表数据拆分为chunk进行checksum计算,由于使用STATEMENT的二进制格式,主库和从库都会进行分别计算,如果主库数据不一致,则会导致this_cnt和this_crc两列的数据不同。

说明:

如下面对`testdb1`.`tb1001`表的`id` >= '4621' and `id` <= '158655'作为一个chunk进行checksum计算并插入到目标表的语句

REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'td1', 'dsns', '1', NULL, NULL, NULL, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `parent_id`, convert(`dsn` using utf8mb4), CONCAT(ISNULL(`parent_id`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `td1`.`dsns` /*checksum table*/

  

然后获取主库的上该chunk的计算值this_cnt和this_crc,将这两值更新到master_crc和master_cnt列中

SELECT this_crc, this_cnt FROM `percona`.`checksums` WHERE db = 'td1' AND tbl = 'dsns' AND chunk = '1'   主库查出crc结果和条数
UPDATE `percona`.`checksums` SET chunk_time = '0.007034', master_crc = '8bbc9dc2', master_cnt = '2' WHERE db = 'td1' AND tbl = 'dsns' AND chunk = '1'  主库写入master的crc和条数

 

 关键执行语句:

2021-04-13T02:42:52.788766Z	  364 Query	DELETE FROM `percona`.`checksums` WHERE db = 'td1' AND tbl = 'dsns'
2021-04-13T02:42:52.793008Z 364 Query USE `td1`
2021-04-13T02:42:52.793339Z 364 Query EXPLAIN SELECT COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `parent_id`, convert(`dsn` using utf8mb4), CONCAT(ISNULL(`parent_id`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `td1`.`dsns` /*explain checksum table*/
2021-04-13T02:42:52.793804Z 364 Query REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'td1', 'dsns', '1', NULL, NULL, NULL, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `id`, `parent_id`, convert(`dsn` using utf8mb4), CONCAT(ISNULL(`parent_id`)))) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `td1`.`dsns` /*checksum table*/
2021-04-13T02:42:52.800891Z 364 Query SHOW WARNINGS
2021-04-13T02:42:52.801264Z 364 Query SELECT this_crc, this_cnt FROM `percona`.`checksums` WHERE db = 'td1' AND tbl = 'dsns' AND chunk = '1'
2021-04-13T02:42:52.801653Z 364 Query UPDATE `percona`.`checksums` SET chunk_time = '0.007034', master_crc = '8bbc9dc2', master_cnt = '2' WHERE db = 'td1' AND tbl = 'dsns' AND chunk = '1'

  

上面更新操作传递到从库上后,从库上的`percona`.`checksums`表便拥有主库的checksum值和从库自己的checksum值,

因此在从库上将master_crc和master_cnt列与this_cnt和this_crc两列进行对比即可以判断该chunk段数据是否有差异。

查看单表差异:

SELECT CONCAT(db, '.', tbl) AS `table`, chunk, chunk_index, lower_boundary, upper_boundary, COALESCE(this_cnt-master_cnt, 0) AS cnt_diff, COALESCE(this_crc <> master_crc OR ISNULL(master_crc) <> ISNULL(this_crc), 0) AS crc_diff, this_cnt, master_cnt, this_crc, master_crc FROM `percona`.`checksums` WHERE (master_cnt <> this_cnt OR master_crc <> this_crc OR ISNULL(master_crc) <> ISNULL(this_crc))  AND (db='td1' AND tbl='dsns')

 执行的全部log:xml改成log格式

https://files.cnblogs.com/files/zping/master.xml

https://files.cnblogs.com/files/zping/slave.xml

pt-table-checksum对比数据测试(dsns方式)的更多相关文章

  1. pt工具校验主从数据一致性之dsns方式

    mysql主从数据一致性校验,常用的方法是Percona-Toolkit的组件pt-table-checksum,这东西怎么用网上一大堆,就不啰嗦了.主要说一下通过dsns方式发现从库的一种方式. p ...

  2. NXP ARM Vector Table CheckSum

    Signature Creator for NXP Cortex-M Devices Algorithm for creating the checksum The reserved Cortex-M ...

  3. MySQL create table as与create table like对比

    a.create table like方式会完整地克隆表结构,但不会插入数据,需要单独使用insert into或load data方式加载数据b.create table as  方式会部分克隆表结 ...

  4. DIV中TABLE居的2种方式

    <html><head><title>测试页面</title></head><body><div width=" ...

  5. SQLAlchemy Table(表)类方式 - Table类和Column类

    Table 构造方法 Table(name, metadata[, *column_list][, **kwargs]) 参数说明: name 表名 metadata 元数据对象 column_lis ...

  6. BootStrap table隐藏列两种方式 (踩坑)

    1.第一种  利用 visible 属性 { field : 'userAccount', title : '订阅人', visible : visible(), formatter:function ...

  7. spring加载配置新旧方式对比

    老方式 1.首先要配置配置文件,如beans.xml,内容如下: <?xml version="1.0" encoding="UTF-8"?> &l ...

  8. Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比

    Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比   上一篇文章: Android自动化测试中AccessibilityService获取控件信息(1 ...

  9. lua中遍历table的几种方式比较

    当我在工作中使用lua进行开发时,发现在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: for key, value in pairs(tbtes ...

  10. bootstrap table分页(前后端两种方式实现)

    bootstrap table分页的两种方式: 前端分页:一次性从数据库查询所有的数据,在前端进行分页(数据量小的时候或者逻辑处理不复杂的话可以使用前端分页) 服务器分页:每次只查询当前页面加载所需要 ...

随机推荐

  1. [转帖]Nginx - 根据IP分配不同的访问后端

    https://www.cnblogs.com/hukey/p/11868017.html 1. 需求分析 为了在线上环境提供测试分支,规定将某IP转发到测试程序地址.如果是 ngx 直接对外,采用 ...

  2. [转帖]Oracle 创建和查看DBLink 的方法

    https://www.cnblogs.com/zhouzangood/articles/4612441.html 1.如果需要创建全局 DBLink,则需要先确定用户有创建 dblink 的权限: ...

  3. kafka学习之五_多个磁盘的性能验证

    kafka学习之五_多个磁盘的性能验证 背景 周末在家学习kafka 上午验证了grafana+kafka_exporter的监控 下午想着验证一把性能相关. kafka学习之三里面,有成套的脚本. ...

  4. [转帖]Python基础之函数(四)

    https://www.jianshu.com/p/168e341fb81c 一.函数定义 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段:比如常用的print(),就是内建函数:通 ...

  5. [转帖][问题已处理]-kubernetes中2次不同的oom处理

    https://dandelioncloud.cn/article/details/1598699030236577793 起因: 同事反馈 服务挂了,kuboard上查看是服务挂掉了,livenes ...

  6. VScode中下载了插件但是无法找到SSH Target连接服务器的解决方法(CANNOT find SSH Target in remote explorer)

    VSCode版本vscode version:(version 1.82) 已下载扩展installed extensions: Remote - SSH v0.106.4 Remote - SSH: ...

  7. 谈JVM xmx, xms等内存相关参数合理性设置

    作者:京东零售 刘乐 说到JVM垃圾回收算法的两个优化标的:吞吐量和停顿时长,并提到这两个优化目标是有冲突的.那么有没有可能提高吞吐量而不影响停顿时长,甚至缩短停顿时长呢?答案是有可能的,提高内存占用 ...

  8. element-plus 按需引入将英文组件修改为中文

    element-plus 默认是英文组件:如下图 将它设置为中文组件 app.vue文件 <template> <el-config-provider :locale="l ...

  9. justify-content: space-between能够对齐的解决办法

    解决办法一 .main{ display: flex; justify-content: space-around; flex-wrap: wrap; } .son{ width:100px } // ...

  10. Gin 框架之jwt 介绍与基本使用

    目录 一.JWT 介绍 二.JWT认证与session认证的区别 2.1 基于session认证流程图 2.2 基于jwt认证流程图 三. JWT 的构成 3.1 header : 头部 3.2 pa ...