pt-table-checksum对比数据测试(dsns方式)
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方式)的更多相关文章
- pt工具校验主从数据一致性之dsns方式
mysql主从数据一致性校验,常用的方法是Percona-Toolkit的组件pt-table-checksum,这东西怎么用网上一大堆,就不啰嗦了.主要说一下通过dsns方式发现从库的一种方式. p ...
- NXP ARM Vector Table CheckSum
Signature Creator for NXP Cortex-M Devices Algorithm for creating the checksum The reserved Cortex-M ...
- MySQL create table as与create table like对比
a.create table like方式会完整地克隆表结构,但不会插入数据,需要单独使用insert into或load data方式加载数据b.create table as 方式会部分克隆表结 ...
- DIV中TABLE居的2种方式
<html><head><title>测试页面</title></head><body><div width=" ...
- SQLAlchemy Table(表)类方式 - Table类和Column类
Table 构造方法 Table(name, metadata[, *column_list][, **kwargs]) 参数说明: name 表名 metadata 元数据对象 column_lis ...
- BootStrap table隐藏列两种方式 (踩坑)
1.第一种 利用 visible 属性 { field : 'userAccount', title : '订阅人', visible : visible(), formatter:function ...
- spring加载配置新旧方式对比
老方式 1.首先要配置配置文件,如beans.xml,内容如下: <?xml version="1.0" encoding="UTF-8"?> &l ...
- Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比
Android自动化测试中AccessibilityService获取控件信息(2)-三种方式对比 上一篇文章: Android自动化测试中AccessibilityService获取控件信息(1 ...
- lua中遍历table的几种方式比较
当我在工作中使用lua进行开发时,发现在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: for key, value in pairs(tbtes ...
- bootstrap table分页(前后端两种方式实现)
bootstrap table分页的两种方式: 前端分页:一次性从数据库查询所有的数据,在前端进行分页(数据量小的时候或者逻辑处理不复杂的话可以使用前端分页) 服务器分页:每次只查询当前页面加载所需要 ...
随机推荐
- java - ArrayList的使用
package list; import java.util.ArrayList; import demo.Hero; public class ListTs { public static void ...
- SQLServer解决deadlock问题的一个场景
SQLServer解决deadlock问题的一个场景 背景 公司产品出现过很多次dead lock 跟研发讨论了很久, 都没有具体的解决思路 但是这边知道了一个SQLServer数据库上面计划100% ...
- drop_caches 的简单学习
drop_caches 的简单学习 背景 最近一段时间一直在学习内存相关的知识 Linux系统里面的内存管理还是非常复杂的. 我这边理解 Linux从宏观层次的 段页式内存管理 到细节的buddy和s ...
- [转帖]VMware ESXi 各版本号对照表
本博文转自以下链接: VMware ESXi Release and Build Number History | virten.net vSphere ESXi 7.0 Name Patch Dat ...
- [转帖]What is Pstate
https://www.jianshu.com/p/342480d917e3 When someone refers to a P-state, generally only the frequenc ...
- [转帖]使用Transformers推理
https://github.com/ymcui/Chinese-LLaMA-Alpaca/wiki/%E4%BD%BF%E7%94%A8Transformers%E6%8E%A8%E7%90%86 ...
- JRC Flink流作业调优指南
# 作者:京东物流 康琪 本文综合Apache Flink原理与京东实时计算平台(JRC)的背景,详细讲述了大规模Flink流作业的调优方法.通过阅读本文,读者可了解Flink流作业的通用调优措施,并 ...
- python2排序
python list cmp排序 对于list的排序一般使用cmp 示例: sorted(xxlist, cmp=self.sortFunc) def sortFunc(self, a, b): r ...
- win10安装wget,从此可以更快的下载文件 and windows10 下 zip命令行参数详解
1.win10安装wget 1.1安装下载 GNU Wget 1.21.3 for Windows 依次如下: 2.将下载好的wget.exe放到 C:/windows/system32文件夹下 也可 ...
- parser.add_argument()用法——命令行选项、参数和子命令解析器
argparse是一个Python模块:命令行选项.参数和子命令解析器.通过使用这种方法,可以在使用 1.argparse简介: argparse 模块是 Python 内置的一个用于命令项选项与参数 ...