(5.10)mysql高可用系列——percona-toolkit工具下的pt-table-checksum 在线验证主从一致性【续写中】
关键词:percona-toolkit 工具包中包含 pt-table-checksum工具,在线验证主从一致性
【1】percona-toolkit 工具包
【1.1】percona-toolkit下载
下载地址:
https://www.percona.com/downloads/percona-toolkit/LATEST/
linux下载/windows直接点击下载 percona-toolkit-3.1.0_x86_64.tar.gz
【1.2】percona-toolkit 安装
#(1)安装perl,需要本地或者网络yum源,参考:yum源配置 yum -y install perl-devel perl-Digest-MD5 perl-DBI perl-DBD-MySQL perl-IO-Socket-SSL.noarch perl-Time-HiRes
#(2)编译安装
需求
* Perl v5.8 or newer
* Bash v3 or newer
* Core Perl modules like Time::HiRes
# perl --version |head -2 #检查perl版本
# bash --version #检查bash版本
快速安装步骤(缺省/usr/local/bin路径下,过程略)
# tar zxvf percona-toolkit-<version>.tar.gz
# cd percona-toolkit-<version>
# perl Makefile.PL (安装到非缺省目录 perl Makefile.PL PREFIX=${HOME})
# make
# make test
# make install
【2】pt-table-checksum学习
(2.1)pt-table-checksum简介
pt-table-checksum是著名的percona-toolkit工具集的其中一种工具。它是一个在线验证主从数据一致性的工具,主要用于以下场景:
1、数据迁移前后,进行数据一致性检查
2、当主从复制出现问题,待修复完成后,对主从数据进行一致性检查
3、把从库当成主库,进行数据更新,产生了“脏数据”
pt-table-checksum原理
1.单行数据checksum值的计算
Pt工具先检查表的结构,并且获取表中每一列的数据类型,把所有数据类型都转化为字符串,然后使用concat_ws()函数进行连接,然后使用crc32计算出该行的checksum值。
2.数据块checksum值的计算
如果一行一行去计算checksum值,再去和从库比较,效率会很低。pt-table-checksum可以利用表中的索引,将表的数据split成一个个chunk,计算的时候也是以chunk为单位。
pt-table-checksum引入了聚合函数BIT_XOR()。它的功能可以理解为将这个chun k内的所有行数据拼接起来,再计算CRC32的值,就得到了这个chunk的checksum值。
3.pt-table-checksum通过在主服务器上执行检查语句
在线检查MySQL复制的一致性,生成replace语句,然后传递到从服务器,再通过update更新master_src的值。通过检测从服务器的this_src和master_src的值从而判断复制是否一致。
pt-table-checksum如何保证checksum的数据一致性?
1.当pt工具在计算主库上某一个chunk的checksum值时,主库可能还在更新,为了保证checksum的是同一份数据。
2.需要对该chunk加for update锁【for update锁需要在事务内才有效,对于不支持事务的MyISAM表,pt工具select加的是全表锁】。
(2.2)pt-table-sync:修复主从数据一致性
pt-table-sync原理:
顾名思义,它用来修复多个实例之间数据的不一致,它可以让主从的数据修复到最终一致。
1.单行数据checksum值的计算
和pt-table-checksum一样,也是先检查表结构,并获取每一列的数据类型,把所有数据类型都转化为字符串,然后用concat_ws()函数进行连接,由此计算出该行的checksum值。Checksum默认采用crc32计算。
2.数据块checksum值的计算
和pt-table-checksum工具一样,pt-table-sync会将表的数据split成若干个chunk,计算的时候以chunk为单位。可以理解为将chunk内的所有行的数据拼接起来,再计算crc32的值,既可以得到该chunk的checksum值。
3.数据修复
前面两步,pt-table-sync与pt-table-checksum的算法和原理是一样的。再往下,就开始有所不同了:
pt-table-checksum只是校验,它把checksum结果存储到统计表,然后把执行过的sql语句记录到binlog,任务就算完成。语句级的复制把计算逻辑传递到从库,并且在从库执行相同的计算。
pt-table-sync则不同,它首先要完成chunk的checksum值计算,一旦发现主从上相同的chunk的checksum值不一样,就会深入到该chunk内部,逐行比较并且修复有问题的行。它的计算逻辑描述如下:
1)、对每一个从库,每一个表,循环进行如下校验和修复过程。
2)、对每一个chunk,校验时加上for update锁。一旦获得锁,就记录下当前主库的show master status值。
3)、在从库上执行select master_pos_wait()函数,等待从库的sql线程执行到show master status得到位置。以此保证,主从上关于这个chunk的内容不再改变。
【select master_pos_wait(‘master_log_file’,’master_log_pos’);该函数会阻塞直到从服务器达到指定的日志文件和偏移量。此时从服务器和主服务器就同步了,语句返回值为0】.
4)、对这个chunk执行checksum计算,然后与主库的checksum进行比较。
5)、如果checksum相同,说明主从数据一致,接着就可以继续下一个chunk。
6)、如果checksum值不同,说明该chunk有不一致。就会深入到chunk内部,逐行计算checksum并比较(单行checksum的比较过程与chunk的比较过程一样,单行实际是chunk的size等于1的特例)。
7)、如果发现某行不一致,则标记下来。继续检测剩余行,直到这个chunk结束。
8)、对找到的主从不一致的行,采用replace into语句,在主库上执行一遍以生成该行全量的binlog, 并同步到从库,这就会以主库数据为基准来修复从库;对于主库有的,而从库没有的行
采用replace into在主库上插入(注意,不能是insert。这分为两种情况:一是有唯一性主键,如果有唯一性主键或者索引,则insert相同记录会在主库上插入失败;
二是没有唯一性主键或者索引,insert相同记录会造成记录重复。故要求pt-table-sync的表必须要有唯一性主键或者索引)。
9)、直到修复该chunk所有不一致的行。继续检查和修复下一个chunk。
10)、直到这个从库上的所有表修复结束。接着继续修复下一个从库。
(2.3)pt-table-checksum
1.pt-table-checksum简介
pt-table-checksum是 Percona-Toolkit的组件之一,用于检测MySQL主、从库的数据是否一致。
原理:
pt-table-checksum运行在主库上,通过show processlist或show slave hosts或DSN方式来确定从库并连接,默认使用crc32算法来进行数据校验。
该工具之所以需要把 binlog 设置为statement格式,是因为该工具能得出主从是否一致所依赖的就是statement基础上同样的SQL语句在主从库上各自的执行结果,也就是数据块的checksum。
主库进行检查后sql语句传给从库,从库执行一遍后,也得到自己的结果,最后,比较主从库上相同数据块的checksum值,由此判断主从数据是否一致。
检测过程根据唯一索引将表按row切分为块(chunk),作为单位计算,可以避免锁表。也不会产生主从延时。
检测时会自动判断复制延迟、 master的负载, 超过阀值后会自动将检测暂停,减小对线上服务的影响。
执行的语句是:
SELECT COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', 各种列名)) AS UNSIGNED)), 10, 16)), 0) AS crc
FROM database.table FORCE INDEX(PRIMARY) WHERE ((id >= '1')) AND ((id <= '1000'))
注意:
# where的条件是根据系统繁忙程度计算出的要执行的范围
# cnt是目前检查的块包括的行数,unsigned是计算出的该块数据的校验值
主从checksum会对比:
如果主库和从库得出的这两个值都是一样的,那数据就是一致的,如果不一样,那就主从不一致,当然,字符集、浮点数之类的问题需要提前规避,以免错判
使用场景:
# pt-table-checksum默认情况下可以应对绝大部分场景,官方说,即使上千个库、上万亿的行,它依然可以很好的工作,这源自于设计很简单。
# 一次检查一个表,不需要太多的内存和多余的操作;必要时,pt-table-checksum 会根据服务器负载动态改变 chunk 大小,减少从库的延迟。
对从库影响:
# 为了减少对数据库的干预,pt-table-checksum还会自动侦测并连接到从库,当然如果失败,可以指定--recursion-method选项来告诉从库在哪里。
# 它的易用性还体现在,复制若有延迟,在从库 checksum 会暂停直到赶上主库的计算时间点(也通过选项--设定一个可容忍的延迟最大值,超过这个值也认为不一致)。
实现原理
1.将 innodb_lock_wait_timeout session 值设置为1。如果 checksum 操作与业务 SQL 出现了锁争⽤,会直接回滚 checksum 操作。
2.将 binlog_format session 会话值设置为 STATEMENT,这样的话,checksum 对应的 REPLACE INTO 操作才会在从库执⾏。
3.创建percona.checksums 表,保存主从数据⼀致性校验的结果。
4.选取分⽚键,⼀般为主键或唯⼀索引。
5.分 chunk 进⾏ checksum 操作
REPLACE INTO `percona`.`checksums` (db, tbl, chunk, chunk_index, lower_boundary,upper_boundary, this_cnt, this_crc) SELECT 'sbtest', 'sbtest1', '1', 'PRIMARY','1', '1000', COUNT(*) AS cnt,
COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#',`id`, `k`, convert(`c` using utf8mb4), convert(`pad` using utf8mb4))) AS UNSIGNED)), 10, 16)), 0) AS crc
FROM `sbtest`.`sbtest1` FORCE INDEX(`PRIMARY`) WHERE ((`id` >= '1')) AND ((`id` <= '1000')) /*checksum chunk*/
6. 每检验完⼀张表,都会在从库进⾏⼀次查询。
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='sbtest' AND tbl='sbtest1')
7.总结
pt-table-checksum 在实现上,会将⼀张⼤表分成多个 chunk,每次针对⼀个 chunk 进⾏校验,校验的结果通过 REPLACE INTO 语句写⼊到 percona.checksums 表中。
然后该语句通过主从复制,在 SLAVE中 同样执⾏⼀次,校验的结果同样是写⼊到 percona.checksums表中。
2.pt-table-checksum在执行中做了什么
pt-table-checksum采用了很多措施来保证检查过程中的安全性,默认参数是可以保障使用安全的,不过参数可以配置,所以需要详细了解参数的功能后再进行更改,否则最好采用默认。
主库: SET SESSION innodb_lock_wait_timeout=1 # 只针对innodb表,保证主数据库安全 SET SESSION wait_timeout=10000 SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION' SET @@binlog_format = 'STATEMENT' SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ SET @@SQL_QUOTE_SHOW_CREATE = 1 # 保证检查安全的相关设置 CREATE DATABASE IF NOT EXISTS percona CREATE TABLE IF NOT EXISTS percona.checksums # 创建校验值存放的库和表 SHOW GLOBAL STATUS LIKE 'Threads_running' # 检查系统运行情况 # 每次用use database来确定数据库并依次只选择一个表进行详细数据量分析 SHOW DATABASES SHOW TABLES FROM database USE database SHOW CREATE TABLE database.a EXPLAIN SELECT * FROM database.a WHERE 1=1 SELECT /!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX(PRIMARY) ORDER BY id LIMIT 1 /first lower boundary/ SELECT /!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX (PRIMARY) WHERE id IS NOT NULL ORDER BY id LIMIT 1 /key_len/ EXPLAIN SELECT /!40001 SQL_NO_CACHE / FROM database.a FORCE INDEX (PRIMARY) WHERE id >= '1' /key_len*/ # 避免之前有过检查并保存有该表的检查信息,将对应信息删掉/ USE percona DELETE FROM percona.checksums WHERE db = 'database' AND tbl = 'a' # 每次检查表时,第一个块的行数固定为1000,之后会根据系统繁忙程度计算出在规定时间内能处理的行数来确定为一个chunk,默认时间为0.5秒,可以更改 USE database EXPLAIN SELECT /!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= '1')) ORDER BY id LIMIT 999, 2 /next chunk boundary/ SELECT /!40001 SQL_NO_CACHE / id FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= '1')) ORDER BY id LIMIT 999, 2 /next chunk boundary
# explain下确定下执行计划,然后开始真正的checksum工作,是用 REPLACE..SELECT语句计算数据情况并将结果插入到checksums表中 EXPLAIN SELECT COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', id, name, type)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= '1')) AND ((id <= '1000')) /explain checksum chunk/ REPLACE INTO percona.checksums (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT 'database', 'a', '1', ' PRIMARY', '1', '1000', COUNT() AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', id, name, type)) AS UNSIGNED)), 10, 16)), 0) AS crc FROM database.a FORCE INDEX(PRIMARY) WHERE ((id >= '1')) AND ((id <= '1000')) /checksum chunk*/ # 检查是否有警告,进一步完善checksums表中的检查信息 SHOW WARNINGS UPDATE percona.checksums SET chunk_time = '0.003725', master_crc = 'a9bd6d97', master_cnt = '1000' WHERE db = 'database' AND tbl = 'a' AND chunk='1' # 以上为一个块的检查结束,开始下一个块或下一个表
从库:
跟主库类似,少了一些设置及explain过程,但多了一个show slave status的检查,来辅助工具判断从库连接和延迟等情况,来确定检查是否继续,暂停还是退出,所有检查执行完后会有这样一个语句来报出检查结果
# 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='database' AND tbl='a')
pt-table-checksum一次只针对一个表,而且会根据表的大小以及当前系统的繁忙程度,计算出一次检查中能包含的数据行数,来尽量避免对线上服务的影响,如果在执行过程中遇到突发的负载增加,还会自动的将检查停下来等待,所以即使面对成千上万的数据库和表时,它也能顺利的进行检查
- 在检查过程中,工具会随时对主从连接情况进行检查,如果从库延迟太大,主从复制中断,检查会停下来等待;这里需要注意的是主从复制过滤,因为这种情形下,主从数据库中的库表存在情况不一致。
- 检查过程中的执行语句会与当前的主从复制过程冲突导致主从复制进程失败,所以如果有过滤存在,需要指定参数--no-check-replication-filters
- 在一个块的数据被检查之前,会先执行explain操作,来确定执行该检查的安全性,如果太大不能在指定时间内完成检查的话就会将该块数据跳过。
- 另外,如果主库上整表的数据特别少或干脆是空表,并不会直接将整表当做一个块去检查,而是会再去从库,确定从库中也是有同样少的数据,避免从库表数据太多却被当成一个块执行造成的从库数据阻塞
- 另外还有一些安全保护设置,在上面的执行流程中已经列出来了,如设置innodb_lock_wait_timeout=1,如果锁等待超过1S,就放弃此次执行
- 在执行过程中如果遇到任何异常,可随时中断进程,如kill或CTRL-C,不会造成任何影响,后面想从此次中断继续检查时,简单的采用--resume就可以
pass
(2.4)pt-table-checksum参数
参数:
0.主库是数据库连接信息 --host --socket --user --password --pid --port 1.指定库 --databases # 要比较的库,--ignore-databases 比较过程中忽略这些库 --databases-regex # --ignore-databases-regex 同上,不过可以用正则匹配 2.指定表 --tables # 要比较的表, --ignore-tables比较过程中忽略这些表 --tables-regex # --ignore-tables-regex 同上,不过可以用正则匹配 3.指定列 --columns # 要比较的列,--ignore-columns 比较过程中忽略这些列 4.直接指定表范围 --where 直接指定表中要比较的范围 5.根据引擎选表 --engines # 比较指定的引擎表, --ignore-engines比较过程中忽略含有这些引擎的表 6.指定连接中断后行为的参数 --resume # 如果主从一致性检查中途中断的话,可以用这个参数来使工具从上次中断时检查的最后一个表开始继续检查 --retries # 如果在检查过程中有非致命性的中断的话,如被kill或者从库延迟等,指定该参数后,工具会自动尝试重连
重点关注的参数:
1.--[no]check-binlog-format
# 默认会检查binlog-format,如果不是statment,就会报错退出,想避免该检查可以设置--no-check-binlog-format
2.--recursion-method
# 参数有四:processlist/hosts/dsn=DSN/no,默认是processlist,hosts,但最好还是指定一下,建议指定--recursion-method=processlist,no一般不使用
# dsn=DSN方法使用时,需要先去库里创建一个表,比如在percona库中建一个dnsn表
# 建表语句:CREATE TABLE dsns (id int(11) NOT NULL AUTO_INCREMENT,parent_id int(11) DEFAULT NULL,dsn varchar(255) NOT NULL,PRIMARY KEY (id));
# 建好后插入主从复制信息数据,如:insert into table dsns(dsn) values(h=slave_host,u=repl_user,p=repl_password,P=port );
# 然后就可以使用DSN方法了:命令为:--recursion-method dsn=D=percona,t=dsns
3.--replicate
# 用来指定存放计算结果的表名, 默认是percona.checksums,工具会默认自动创建库percona和表checksums并将checksum的检查结果输入到这个表中,如果自己用该参数去指定表的话,
# 表结构必须是:
# CREATE TABLE checksums ( db char(64) NOT NULL, tbl char(64) NOT NULL, chunk int NOT NULL, chunk_time float NULL, chunk_index varchar(200) NULL, lower_boundary text NULL, upper_boundary text NULL, this_crc char(40) NOT NULL, this_cnt int NOT NULL, master_crc char(40) NULL, master_cnt int NULL, ts timestamp NOT NULL, PRIMARY KEY (db, tbl, chunk), INDEX ts_db_tbl (ts, db, tbl) ) ENGINE=InnoDB; # 需要注意的是存储引擎设置,如果检查的表是innodb表,就设置innodb引擎,如果检查的表和checksums表的引擎不一致,如分别是myisam和innodb,会引起复制错误:“different error on master and slave.”!!!
其他参数
1.--[no]check-replication-filters
# 默认在检查到在主从复制过程中有被用..ignore..过滤掉的表,检查会中断并退出,如果想避开这个检查可以设置--no-check-replication-filters
2.--chunk-index(type: string)
# 工具默认在分块时会选取最合适的索引来explain确定chunk的大小,但如果你希望用其他索引来执行,可以用该参数来指定,工具会以FORCE INDEX的形式把指定的索引加进去
3.--chunk-index-columns(type: int)
# 可以用来指定组合索引中使用前几个列来辅助分块
4.--chunk-size
# 直接确定chunk的大小,默认1000行数据,但不建议使用,建议使用--chunk-time代替
5.--chunk-time
# 默认是0.5秒,工具会根据当前系统运行繁忙程度计算出在该指定时间内可以处理的数据行数(即chunk),比较灵活
6.--[no]empty-replicate-table
# 默认yes,每次检查表之前都去把checksums表中已有的该表信息删掉,以利于后续重新插入新检查信息
7.--float-precision(type: int)
# 设置浮点数的四舍五入方式,以避免不同版本间或其他特定情况中,主从间因浮点数四舍五入的方式不同而导致查出不一致,
# If you specify a value of 2, for example, then the values 1.008 and 1.009 will be rounded to 1.01, and will checksum as equal
8.--function
# 计算checksum值时的函数,默认是CRC32,其他还有FNV1A_64, MURMUR_HASH, SHA1, MD5等
9.--max-lag
# 默认1S,主从最大延迟,超过这个延迟时间,就会停下来等待从库同步,确定方法是采用Seconds_Behind_Master的值
10.--progress
# 指定后可以按设定的参数将执行过程中的运行情况输出到STDERR,如主从延迟时从库的等待,等待时间等,指定时后跟两个参数值,默认是 "time,30",前一个参数有:percentage, time, or iterations;后一个指定百分比,具体时间或者间隔的数目
【参数常⽤参数】
--replicate-check-only:# 直接根据 percona.checksums 表的内容输出主从差异结果,不做任何校验。
过滤相关
--databases,--ignore-databases,--databases-regex,--ignore-databases-regex,--tables,--ignoretables,--tables-regex,--ignore-tables-regex,--columns,--ignore-columns,--engines,--ignoreengines,--where
主从相关
--recurse,--recursion-method,--check-slave-lag,--skip-check-slave-lag,
pt-table-checksum 在运⾏的过程中,会以固定频率(默认1s)检测从库的复制情况,如果从库停⽌或延迟超过⼀定的阈值( 默认1s),则会暂停当前的操作,直到复制恢复。
性能相关
--chunk-size,--chunk-time
# 前者指定 chunk 的⼤⼩,默认为 1000。后者指定 chunk 的查询时间,默认为 0.5s。默认使⽤的是后者,基于查询时间⾃动调节 chunk 的⼤⼩。
--max-load
# 基于数据库的负载情况⾃动调节校验操作。默认为 Threads_running=25。
输出相关
--explain # 只打印 checksum 操作,不实际执⾏。
--quiet # 只会输出 error,warning 和主从数据不⼀致的信息。
(2.5)常见用法及输出结果
实例校验 # 不指定库,监测所有数据库(除information_schema、percona、performance_schema库)
# pt-table-checksum h=127.0.0.1,P=3306,u=root,p=123456 --no-check-binlog-format
指定库校验 # 多个库之间⽤逗号隔开。
# pt-table-checksum h=127.0.0.1,P=3306,u=root,p=123456 --no-check-binlog-format --databases sbtest,db1
指定表校验
# pt-table-checksum h=127.0.0.1,P=3306,u=root,p=123456 --no-check-binlog-format --tables db1.t1,sbtest.sbtest1
输出结果:
TS :完成检查的时间。
ERRORS :检查时候发生错误和警告的数量。
DIFFS :0表示一致,1表示不一致。当指定--no-replicate-check时,会一直为0,当指定--replicate-check-only仅仅显示数据不一致的表信息。
ROWS :表的行数。
CHUNKS :被划分到表中的块的数目。
SKIPPED :由于错误或警告或过大,则跳过块的数目。
TIME :执行的时间。
TABLE :被检查的表名。
可以看到,最后的结果中检测行数是2,DIFFS是0,也就是没有检测出来不同,这和我们的预期不符。继续查看percona官方文档,发现该命令有如下限制。
数据不一致如何修复?
可以利用pt-table-sync来进行修复。
该工具可以使用--sync-to-master参数结合--print参数来打印出来修复从库所需要的SQL文本,然后再从库上执行这些SQL脚本修复即可。
关于pt-table-sync可以参看percona官方文档:
https://www.percona.com/doc/percona-toolkit/LATEST/pt-table-sync.html
由于在binlog_format=row模式下无法使用,pt-table-checksum工具,所以这个pt-table-sync工具我就没有测试,有兴趣的同学可以自行了结下。
(2.6)常见问题以及报错信息
特别特别重要的参数
1.为了保证主数据库服务的安全,该工具实现了许多保护措施:
# 自动设置 innodb_lock_wait_timeout 为1s,避免引起
# 默认当数据库有25个以上的并发查询时,pt-table-checksum会暂停。可以设置 --max-load 选项来设置这个阀值
# 当用 Ctrl+C 停止任务后,工具会正常的完成当前 chunk 检测,下次使用 --resume 选项启动可以恢复继续下一个 chunk
2.发现从库的方式--recursion-method参数
(1)在有些情况下,recursion-method如果不设会报错:Diffs cannot be detected because no slaves were found.
# 其参数有四
# processlist,使用show full processlist方式来查找从库
# hosts,使用show slave hosts方式来查找从库,从库需要设置rehost和report参数
# dsn=DSN,使用命令行方式来查找从库
# no,不准备找从库
(2)主从的端口必须一致,如果不一致就需要用DSN方法进行指定,否则会报找不到从库的错误,如果能连到从库服务器但没有指定端口,默认会寻找3306端口
(3)被检查的主从binlog_format必须为statement,如果不是statement-based,那就添加参数--no-check-binlog-format来避开binlog格式检查
(4)检查结果会输出到默认建立的percona库中的checksums表中,并会输出统计信息到屏幕,diffs列展示主从数据不一致的块的数目,如果都是0,恭喜,数据是一致的
3.pt-table-checksum默认是检查binlog_format=statement的binlog
# 如果不是statement-based,那就添加参数--no-check-binlog-format来避开binlog格式检查
常见问题
问题1
1.创建表结构
create table t1(id int primary key auto_increment,name varchar(32) not null);
2.插入数据
insert into t1 values(1,"admin"),(2,"kobe"),(3,"test");
3.从库t1新增一列
alter table t1 add sex int;
4.主从数据校验
[root@host1 backup]# pt-table-checksum --host='192.168.81.200' --user='root' --password='root@123' --port=3306 --databases info --tables t1 --no-check-binlog-format --recursion-method=processlist Checking if all tables can be checksummed ... Starting checksum ... TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE 10-20T01:42:17 0 0 3 0 1 0 0.347 info.t1 [root@host1 backup]#
5.从库进行查询结果
mysql> select * from percona.checksums where master_cnt <> this_cnt or master_crc <> this_crc; Empty set (0.00 sec)
(2.7)检查差异
(1)通过已经生成的 checksums表
[root@JR-MySQL-A1 data]# pt-table-checksum -h 10.18.51.33 -u checksum -p 'Checksum@31jr' --nocheck-binlog-format --nocheck-replication-filters --recursion-method dsn=D=clover,t=dsns --databases db_financial,db_mobsbase,db_order --replicate-check-only Checking if all tables can be checksummed ... Starting checksum ... Differences on JR-MySQL-A1 TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY db_financial.t_mq_receive_message 5 -2 1 PRIMARY 931840 1090060 db_mobsbase.options_info 26 -2 1 PRIMARY 7652828 7973872
(2)直接查询 checksums表
select * from checksums where this_crc!=master_crc or this_cnt!=master_cnt;
(2.8)总结
# 虽然现在从库的表已经添加了一列,不完全一致,但是此工具仍然认为主从是一致的,这可能跟工具的原理有关,因为把所有列拼接为长子串的时候,空列不会影响md5值得运算结果,需要看这个工具后续更新会不会解决这个问题
问题2:在检查阶段,超过1000行的数据,如果没有设定索引或者主键,则报错,该表会跳过检查。
问题3:在修复阶段,如果表没有设置主键或索引,则修复报错,可以手动进行修复。
问题4:监测是基于块进行的,如果mysql表的数据没有进行分块,那么当表过大时,会造成监测一段时间后发现没有问题会跳过改表。
问题5:当数据库两个数据不一致,但是checksum检测一致时,没有比对出不一致。主库和从库账号一致,密码不一致发现了这种问题。
原因:对于修改密码的操作,chencksum的值并没有发生变化。
常见报错信息
1.监测报错(找不到从库,使用--recursion-method指定模式)
# Diffs cannot be detected because no slaves were found. Please read the --recursion-method documentation for information.
2.binlog模式问题(由于指定为row行复制造成 使用--no-check-binlog-format跳过监测,不过这样有可能监测不出来主从不一致的信息,row行模式对于主从来说不需要进行主从监测)
# Replica centos-1 has binlog_format ROW which could cause pt-table-checksum to break replication.
# Please read "Replicas using row-based replication" in the LIMITATIONS section of the tool's documentation. If you understand the risks, specify --no-check-binlog-format to disable this check.
3.没有索引或主键导致的,在数据较少的时候(低于1000行,没有测试出该信息,超过1000行会报错)
# Cannot checksum table test.t: There is no good index and the table is oversized. at ./pt-table-checksum line 6370.
4.等待信息,已检测的百分比,这是因为设置了主键但是没有索引导致没有分块且表过大造成。
# Checksumming database.table: 27% 01:17 remain
【2】pt-table-checksum工具
(经常会有环境BUG,有时候死活跑不出来)
【2.1】pt-table-checksum的应用场景
(1)数据库迁移后验证数据
(2)主从复制出现问题,需要修复
(3)不小心误操作,主从数据库高反了,产生了错误的数据。
(4)定期校验数据
【2.2】基本使用
基本使用参考:https://blog.csdn.net/jswangchang/article/details/79501553?tdsourcetag=s_pctim_aiomsg
详细参数参考:https://www.xin3721.com/ArticleMySQL/mysql14224.html
官方资料:https://www.percona.com/doc/percona-toolkit/LATEST/pt-table-checksum.html
生产环境下使用经验:https://segmentfault.com/a/1190000004309169
使用方法:
pt-table-checksum [OPTIONS] [DSN]
pt-table-checksum
:在主(master)上通过执行校验的查询对复制的一致性进行检查,对比主从的校验值,从而产生结果。
如何知道自己有哪些从库呢?show slave hosts;
DSN指向的是主的地址,该工具的退出状态不为零,如果发现有任何差别,或者如果出现任何警告或错误,更多信息请查看官方资料。
(1)对比一个表
pt-table-checksum --nocheck-replication-filters --replicate=yggl.checksums --databases=yggl --tables=salary h=127.0.0.1,u=root,p=123456,P=3306
详细使用务必参考: http://www.xuchanggang.cn/archives/938.html
【3】pt-table-checksum最佳实践
【3.1】检查主从数据的一致性情况:
pt-table-checksum [OPTIONS] [DSN]。
pt-table-checksum:在主上通过执行校验的查询对复制的一致性进行检查,对比主从的校验值,从而产生结果。
DSN指向的是主的地址,该工具的退出状态不为零,如果发现有任何差别,或者如果出现任何警告或错误,不指定任何参数,会直接对本地的所有数据库的表进行检查。
如pt-table-checksum u=root,p=123456
注意事项如下:
(1).测试需要一个既能登录主库,也能登录从库,而且还能同步数据库的账号;
(2).只能指定一个host,必须为主库的IP;
(3).在检查时会向表加S锁;
(4).运行之前需要从库的同步IO和SQL进程是YES状态。
mysql> GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'checksums'@'x.x.x.x' IDENTIFIED BY ‘xxxx’;
(5).如果在配置主从时,忽略复制mysql库时,需要在 主上 和 从上 都执行上面的授权语句
[root@mysql-master1 ~]# pt-table-checksum h=’172.16.10.53′,u=’checksums’,p=’checksums’,P=3306 -d test_0109 \
–nocheck-replication-filters –replicate=test_checksum.checksums –nocheck-binlog-format –nocheck-plan –recursion-method=hosts Waiting to check replicas for differences: 0% 00:00 remain TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE 01-12T14:39:51 0 0 0 1 0 0.024 test_0109.broker 01-12T14:39:51 0 0 4 1 0 0.010 test_0109.check_conistent 01-12T14:39:51 0 0 0 1 0 0.012 test_0109.partner_alert_rule 01-12T14:39:51 0 1 0 1 0 0.266 test_0109.proc_test 01-12T14:39:51 0 1 529 1 0 0.021 test_0109.project
类似如下图:
参数说明:
TS :完成检查的时间。
ERRORS :检查时候发生错误和警告的数量。
DIFFS :0表示一致,1表示不一致。当指定–no-replicate-check时,会一直为0,当指定–replicate-check-only会显示不同的信息。
ROWS :表的行数。
CHUNKS :被划分到表中的块的数目。
SKIPPED :由于错误或警告或过大,则跳过块的数目。
TIME :执行的时间。
TABLE :被检查的表名。
参数意义:
–nocheck-replication-filters :不检查复制过滤器,建议启用。后面可以用–databases来指定需要检查的数据库。
–no-check-binlog-format : 不检查复制的binlog模式,要是binlog模式是ROW,则会报错。
–replicate-check-only :只显示不同步的信息。
–replicate= :把checksum的信息写入到指定表中,建议直接写到被检查的数据库当中。
–databases= :指定需要被检查的数据库,多个则用逗号隔开。
–tables= :指定需要被检查的表,多个用逗号隔开
–recursion-method=: 主机信息
h=172.16.10.53 :Master的地址
u=checksums :用户名
p=checksums :密码
P=3306 :端口
通过DIFFS是1可以看出主从的表数据不一致。通过查看从库上的 test_checksum.checksums 表可以看到主从库的检验信息。
mysql> select * from test_checksum.checksums;
+———–+——————–+——-+————+————-+—————-+—————-+———-+———-+————+————+———————+
| db | tbl | chunk | chunk_time | chunk_index | lower_boundary | upper_boundary | this_crc | this_cnt | master_crc | master_cnt | ts |
+———–+——————–+——-+————+————-+—————-+—————-+———-+———-+————+————+———————+
| test_0109 | broker | 1 | 0.005901 | NULL | NULL | NULL | 0 | 0 | 0 | 0 | 2015-01-12 14:39:51 |
| test_0109 | check_conistent | 1 | 0.000484 | NULL | NULL | NULL | 709a8dc | 4 | 709a8dc | 4 | 2015-01-12 14:39:51 |
| test_0109 | partner_alert_rule | 1 | 0.000825 | NULL | NULL | NULL | 0 | 0 | 0 | 0 | 2015-01-12 14:39:51 |
| test_0109 | proc_test | 1 | 0.000439 | NULL | NULL | NULL | 652c8c22 | 99 | 0 | 0 | 2015-01-12 14:39:51 |
| test_0109 | project | 1 | 0.006852 | NULL | NULL | NULL | 0 | 0 | 862da9de | 529 | 2015-01-12 14:39:51 |
+———–+——————–+——-+————+————-+—————-+—————-+———-+———-+————+————+———————+
通过上面的 this_crc <> master_crc 更能清楚的看出他们的不一致了,通过chunk知道是这个张表的哪个块上的记录出现不一致。
要是主的binlog模式是Row 则会报错:
Replica db2 has binlog_format ROW which could cause pt-table-checksum to break replication.
Please read “Replicas using row-based replication” in the LIMITATIONS section of the tool’s documentation.
If you understand the risks, specify –no-check-binlog-format to disable this check.
指定–replicate-check-only参数会在前一次pt-table-checksum检验的数据之上比较(不会再执行计算),显示出数据不一致的SLAVE主机名
【3.2】修复主从数据不一致的情况
通过上面的工具,我们检测出主从之间数据不一致的情况,那此时我们应该如何处理呢?
percona提供了pt-table-sync 用于修复主从数据的一致性
pt-table-sync [OPTIONS] DSN [DSN]。
pt-table-sync: 高效的同步MySQL表之间的数据,他可以做单向和双向同步的表数据。他可以同步单个表,也可以同步整个库。它不同步表结构、索引、或任何其他模式对象。所以在修复一致性之前需要保证他们表存在。
继续上面的复制环境,主和从的表数据不一致,需要修复
pt-table-sync –print –replicate=test_checksum.checksums h=172.16.10.53,u=checksums,p=checksums,P=3306 h=172.16.10.55,u=checksums,p=checksums,P=3306
// 先MASTER的IP,再SLAVE的IP
// 以上是打印出同步语句,如果不一致数据较多,不需要打印出这些语句;
参数意义参考:
–replicate= :指定通过pt-table-checksum得到的表,这2个工具差不多都会一直用。
–databases= : 指定执行同步的数据库,多个用逗号隔开。
–tables= :指定执行同步的表,多个用逗号隔开。
–sync-to-master :指定一个DSN,即从的IP,他会通过show processlist或show slave status 去自动的找主。
h=127.0.0.1 :服务器地址,命令里有2个ip,第一次出现的是M的地址,第2次是Slave的地址。
u=root :帐号。
p=123456 :密码。
–print :打印,但不执行命令。
–execute :执行命令。
执行数据修复:
pt-table-sync –execute –replicate=test_checksum.checksums h=172.16.10.53,u=checksums,p=checksums,P=3306 h=172.16.10.55,u=checksums,p=checksums,P=3306
此时,再检测主从数据一致性,发现主从数据已经一致了:
[root@mysql-master1 ~]# pt-table-checksum h=’172.16.10.53′,u=’checksums’,p=’checksums’,P=3306 -d test_0109 \
–nocheck-replication-filters –replicate=test_checksum.checksums –nocheck-binlog-format –nocheck-plan –recursion-method=hosts TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE 01-12T14:54:16 0 0 0 1 0 0.018 test_0109.broker 01-12T14:54:16 0 0 4 1 0 0.008 test_0109.check_conistent 01-12T14:54:16 0 0 0 1 0 0.008 test_0109.partner_alert_rule 01-12T14:54:16 0 0 0 1 0 0.016 test_0109.proc_test 01-12T14:54:16 0 0 529 1 0 0.273 test_0109.project
附:
以下错误处理方式:
(1).要是表中没有唯一索引或则主键则会报错:
Can’t make changes on the master because no unique index exists at /usr/local/bin/pt-table-sync line 10591.
(2).要是从库有的数据,而主库没有,那这个数据怎么处理?
会给出删除SLAVE多余数据,和修复SLAVE缺失数据的SQL语句。
(3).该工具执行检查表动作,检查连接的帐号需要有很高的权限,在一般权限上需要加SELECT, PROCESS, SUPER, REPLICATION SLAVE等权限。
pt-table-checksm 配合pt-table-sync使用,在执行pt-table-sync数据同步之前,一定要执行pt-table-checksm命令检查。
(4).手动执行pt-table-checksum时会出现Diffs cannot be detected because no slaves were found. Please read the –recursion-method documentation for information.
从字面意思上看是,主库找不到从数据库。只需要在从库配置文件/具体目录/my.cnf中添加
report_host=slave_ip
report_port=slave_port
即可。
也可以在pt-table-checksum –recursion-method=hosts
默认是通过show processlist 找到host的值或show slave hosts 找到host的值。
【3.3】我的实践
(1)检查同步
在主库/从库都可以运行
pt-table-checksum --nocheck-replication-filters --replicate=test.checksum --databases=test h=127.0.0.1,u=root,p=123456,P=3306 --no-check-binlog-format
#pt-table-checksum --nocheck-replication-filters --replicate=test.checksum --databases=test h='主库IP',u='root',p='123456',P=3306 --no-check-binlog-format --recursion-method=processlist
(2)构造问题
在从库插入一条数据。因为之前插入了一条数据ID为5,但删除掉了,所以这里再插入一条数据,id自动变成了6
主库数据如下:
(3)再次检查
发现已经有误差了。
(4)使用 pt-table-sync 修复
左边的h 是主库,右边的 h 是从库
pt-table-sync --print --replicate=test.checksum h=127.0.0.1,u=root,p=123456,P=3306 h=192.168.1.201,u=root,p=123456,P=3306
Errors in command-line arguments: 必须要有以下3个选项其中一个,否则会报错。
* Specify at least one of --print, --execute or --dry-run
这里使用了 --print ,所以会自动打印出来,因为我们这里是,从库比主库数据多。
所以这里给出的是删除从库多余数据的SQL;
然后执行后,解决
pt-table-sync --execute --replicate=test.checksum h=127.0.0.1,u=root,p=123456,P=3306 h=192.168.1.201,u=root,p=123456,P=3306
【4】percona-toolkit工具包下的所有工具
【4.1】官网文档
官网说明参考:https://www.percona.com/doc/percona-toolkit/LATEST/index.html
【4.2】主要工具介绍
如果是非源码安装或源码安装是未指定路径,缺省情况下所有的pt相关的工具位于/usr/bin目录下,以pt-开头。
获取有关命令行的帮助信息,直接在shell提示符下输入命令行与--hlep即可。如: /usr/bin/pt-upgrade --help
# ls -hltr /usr/bin/pt-*
pt-upgrade
#该命令主要用于对比不同mysql版本下SQL执行的差异,通常用于升级前进行对比。
#会生成SQL文件或单独的SQL语句在每个服务器上执行的结果、错误和警告信息等。
pt-online-schema-change
#功能为支持在线变更表构,且不锁定原表,不阻塞原表的DML操作。
#该特性与Oracle的dbms_redefinition在线重定义表原理基本类似。
pt-mysql-summary
#对连接的mysql服务器生成一份详细的配置情况以及sataus信息
#在尾部也提供当前实例的的配置文件的信息
pt-mext
#并行查看SHOW GLOBAL STATUS的多个样本的信息。
#pt-mext会执行你指定的COMMAND,并每次读取一行结果,把空行分割的内容保存到一个一个的临时文件中,最后结合这些临时文件并行查看结果。
pt-kill
#Kill掉符合指定条件mysql语句
pt-ioprofile
#pt-ioprofile的原理是对某个pid附加一个strace进程进行IO分析
pt-fingerprint
#用于生成查询指纹。主要将将sql查询生成queryID,pt-query-digest中的ID即是通过此工具来完成的。
#类似于Oracle中的SQL_ID,涉及绑定变量,字面量等
pt-find
#用与查找mysql表并执行指定的命令,类似于find命令
pt-fifo-split
#模拟切割文件并通过管道传递给先入先出队列而不用真正的切割文件
pt-deadlock-logger
#用于监控mysql服务器上死锁并输出到日志文件,日志包含发生死锁的时间、死锁线程id、死锁的事务id、发生死锁时事务执行时间等详细信息。
pt-archiver
#将mysql数据库中表的记录归档到另外一个表或者文件
#该工具具只是归档旧的数据,对线上数据的OLTP查询几乎没有影响。
#可以将数据插入另外一台服务器的其他表中,也可以写入到一个文件中,方便使用load data infile命令导入数据。
pt-agent
#基于Percona Cloud的一个客户端代理工具
pt-visual-explain
#用于格式化explain的输出
pt-variable-advisor
#用于分析mysql系统变量可能存在的一些问题,可以据此评估有关参数的设置正确与否。
pt-stalk
#用于收集mysql数据库故障时的相关信息便于后续诊断处理。
pt-slave-delay
#用于设定从服务器落后于主服务器的时间间隔。
#该命令行通过启动和停止复制sql线程来设置从落后于主指定时间。
#用于浏览pt-stalk生成的文件。
pt-show-grants
#将当前实例的用户权限全部输出,可以用于迁移数据库过程中重建用户。
pt-query-digest
#用于分析mysql服务器的慢查询日志,并格式化输出以便于查看和分析。
pt-pmp
#为查询程序执行聚合的GDB堆栈跟踪,先进性堆栈跟踪,然后将跟踪信息汇总。
pt-index-usage
#从log文件中读取查询语句,并用分析当前索引如何被使用。
#完成分析之后会生成一份关于索引没有被查询使用过的报告,可以用于分析报告考虑剔除无用的索引。
pt-heartbeat
#用于监控mysql复制架构的延迟。
#主要是通过在主库上的--update线程持续更新指定表上的一个时间戳,从库上--monitor线程或者--check线程检查主库更新的时间戳并与当前系统时间对比,得到延迟值。
pt-fk-error-logger
#将外键相关的错误信息记录到日志或表。
pt-duplicate-key-checker
#功能为从mysql表中找出重复的索引和外键,这个工具会将重复的索引和外键都列出来
#同时也可以生成相应的drop index的语句
pt-diskstats
#类似于iostat,打印磁盘io统计信息,但是这个工具是交互式并且比iostat更详细。可以分析从远程机器收集的数据。
pt-config-diff
#用于比较mysql配置文件和服务器变量
#至少2个配置源需要指定,可以用于迁移或升级前后配置文件进行对比
pt-align
#格式化输出
pt-slave-find
#连接mysql主服务器并查找其所有的从,然后打印出所有从服务器的层级关系。
pt-table-checksum
#用于校验mysql复制的一致性。
#该工具主要是高效的查找数据差异,如果存在差异性,可以通过pt-table-sync来解决。
#用户慢查询分析
#根据执行时间,锁时间,执行次数,等等综合分析
【故障排查】
(1)Diffs cannot be detected because no slaves were found
不能自动找到从库,确认processlist或host或dsns方式用对了。建议在从库的配置文件中加上
report_host = MASTER_HOST
report_port = 13306
注: (1)在有些情况下,recursion-method如果不设会报错:Diffs cannot be detected because no slaves were found.
其参数有四:processlist/hosts/dsn=DSN/no,用来决定查找slave的方式是show full processlist还是show slave hosts还是命令行直接指定还是压根就不准备找从库,具体见下面参数介绍
(2)主从的端口必须一致
如果不一致就需要用DSN方法进行指定,否则会报找不到从库的错误,如果能连到从库服务器但没有指定端口,默认会寻找3306端口
案例: https://bbs.csdn.net/topics/390531787
问题: 我在使用pt-table-checksum检查主从数据是否一致遇到的问题:
一个主,两个从
主:192.168.11.50 端口3306
从1:192.168.11.64 端口3306
从2:192.168.11.74 端口3307
pt-table-checksum可以很容易检查从1的数据是否一致,但是从2因为端口是3307,连接不上,如何解决?
解决:
在Master机的test库加入 CREATE TABLE `dsns` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULT NULL, `dsn` varchar(255) NOT NULL, PRIMARY KEY (`id`) ); – 写入从库信息 INSERT INTO dsns (parent_id,dsn) values(1,'h=192.168.11.64,u=checksums,p=123456,P=3306'); – 如果有多个从库,就插入多条记录. INSERT INTO dsns (parent_id,dsn) values(1,'h=192.168.11.74,u=checksums,p=123456,P=3307'); 执行pt-table-checksum命令时多加下面的参数即可。 --recursion-method=dsn=h=192.168.11.103,D=test,t=dsns
(3)被检查的主从binlog_format必须为statement,如果不是statement-based,那就添加参数--no-check-binlog-format来避开binlog格式检查
(4)检查结果会输出到默认建立的percona库中的checksums表中,并会输出统计信息到屏幕,diffs列展示主从数据不一致的块的数目,如果都是0,恭喜,数据是一致的
(2)Cannot connect to h=slave1.*.com,p=...,u=percona_user
可以在pt-table-checksum命令前加PTDEBUG=1来看详细的执行过程,如端口、用户名、权限错误。
(3)Waiting for the --replicate table to replicate to XXX 问题出在 percona.checksums
表在从库不存在,根本原因是没有从主库同步过来,所以看一下从库是否延迟严重。
(4)Pausing because Threads_running=25 反复打印出类似上面停止检查的信息。
这是因为当前数据库正在运行的线程数大于默认25,pt-table-checksum 为了减少对库的压力暂停检查了。等数据库压力过了就好了,或者也可以直接 Ctrl+C 终端,
下一次加上--resume继续执行,或者加大--max-load=值。
(5)字符集问题
Error checksumming table Error executing checksum query: DBD::mysql::st execute failed: Illegal mix of collations 12-17T14:48:04 Error checksumming table d_ec_cs.t_online_cs: Error executing checksum query: DBD::mysql::st execute failed: Illegal mix of collations for operation 'concat_ws' [for Statement "REPLACE INTO `percona`.`ali_checksum` (db, tbl, chunk, chunk_index, lower_boundary, upper_boundary, this_cnt, this_crc) SELECT ?, ?, ?, ?, ?, ?, COUNT(*) AS cnt, COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(CONCAT_WS('#', `f_cs_id`, `f_corp_id`, `f_valid`, `f_show_name`, `f_online_msg`, `f_offline_msg`, `f_show_mobile`, `f_group_id`, `f_qq`, `f_show_qq`, `f_msn`, `f_show_msn`, `f_sms_online`, `f_scheme`, `f_tel`, `f_telno`, `f_show_tel`, `f_contact`, `f_mobile`, `f_position`, `f_other1`, `f_other2`, `f_other_text1`, `f_other_text2`, `f_email`, `f_qq_first`, `f_qq_first_type`, `f_aids_open`, `f_aids_qq`, `f_aids_crmqq`, `f_aids_yahoo`, `f_aids_skype`, `f_aids_aliww`, `f_aids_msn`, `f_aids_alibaba`, `f_aids_alitrade`, CONCAT(ISNULL(`f_show_name`), ISNULL(`f_group_id`), ISNULL(`f_qq`), ISNULL(`f_show_qq`), ISNULL(`f_sms_online`), ISNULL(`f_other_text1`), ISNULL(`f_other_text2`), ISNULL(`f_email`)) )) AS UNSIGNED)), 10, 16)), 0) AS crc FROM `d_ec_cs`.`t_online_cs` /*checksum table*/" with ParamValues: 0='d_ts_profile', 1='t_user_account', 2=1, 3=undef, 4=undef, 5=undef] at /usr/bin/pt-table-checksum line 10520. 是个bug,暂时无法解决,Illegal mix of collations for operation 'concat_ws'。
(6)Replica JR-MySQL-B2 is stopped. Waiting.
没有解决,疑惑,我的主从明明就是正常的。
【参考文档】
排错:https://blog.csdn.net/qq_39408664/article/details/119445937
pt-table-checksum:https://www.cnblogs.com/dbabd/p/10653408.html#autoid-1-2-0
pt-table-sync:https://www.cnblogs.com/dbabd/p/10690429.html