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. [转帖]Oracle如何重启mmon/mmnl进程(AWR自动采集)

    https://www.cnblogs.com/jyzhao/p/10119854.html 学习一下 环境:Oracle 11.2.0.4 RAC现象:sysaux空间满导致无法正常生成快照,清理空 ...

  2. [转帖]Lightning 实操指南

    2.2.2 Lightning 实操指南 这一节将介绍如何使用 Lightning 导入数据的实操 2.2.2.1 TiDB Lightning 快速开始 注意 TiDB Lightning 运行后, ...

  3. Docker 镜像减少体积的思路和方法

    Docker 镜像减少体积的思路和方法 背景 有一个项目感觉镜像有点大 这边同事喊着一起帮忙处理一下. 今天基本上就在客户现场进行处理了. 想着应该把自己想到的东西整理一下. 整体思路 1. 清理do ...

  4. [转帖]Kdump调试机理详细总结(一)

    https://blog.csdn.net/luckiers/category_11796393.html 一.简介 本文主要讲解Kdump的运行机理,后续两个章节会详细介绍kdump的使用和如何分析 ...

  5. 麒麟信安V3.4 安装PG15的过程V2.0

    改版说明 上一次进行了PG的安装当时发现自己少加了一部分ossp的处理. 这里补充上...不然挺浪费时间的. 背景 发现基于OpenEuler的几个系统使用CentOS的rpm包 安装PG数据库时有问 ...

  6. OpenPower服务使用node-exporter prometheus以及grafana进行性能监控的流程

    OpenPower服务器性能监控操作流程 1. 前言 最近看了很多prometheus以及influxdb进行性能监控的帖子,简单学习了下influxdb是一个单纯的时序数据库,prometheus是 ...

  7. .Net Core 3.1浏览器后端服务(二) Web API项目分层

    一.前言 分层开发的思想在计算机领域中至关重要,从操作系统到软件设计,分层思想无处不在. 在搭建项目的分层结构前,先简单了解下分层的优缺点.如下图,分为(呈现层.业务层.服务层.数据层) 分层的优点: ...

  8. linux中如何统计千万个文件总和

    很简单.很简单.很简单.重要事情说三遍 命令:ls | grep '匹配信息' | wc -l ls查看该目录下的所有文件,果然隐藏文件也要匹配上的话,需要:ls -a grep匹配,如查看文件中有. ...

  9. 【一个小发现】VictoriaMetrics 中 vmselect 的 `-search.denyPartialResponse` 选项不应该开启

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 一直以为vmselect 的 -search.denyPa ...

  10. .net fromwork连接rabbitmq发布消息

    1.创建连接工厂类 var factory = new RabbitMQ.Client.ConnectionFactory() { HostName = "120.237.72.46&quo ...