MySQL如何对主从数据不一致的情况进行校验并继续同步

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 两台MySQL,发生了种种种种,导致了两个表的数据不一致,但是同步还在正常进行,后来意识到这种问题(可能之前skip啊,或者一开始搭建的时候就是不一致的状态),该如何修复呢?
两台MySQL,发生了种种种种,导致了两个表的数据不一致,但是同步还在正常进行,后来意识到这种问题(可能之前skip啊,或者一开始搭建的时候就是不一致的状态),该如何修复呢?

我们看可以来看下percona-toolkit这个工具是如何修复这种情况的

校验:
主库:192.168.100.8 3306
从库:192.168.100.12 3305
MySQL version:MySQL-5.6.30

1.master 服务器安装yum依赖包

yum install perl perl-devel perl-Time-HiRes perl-DBI perl-DBD-MySQL

2.安装percona-toolkit工具包

wget http://www.percona.com/get/percona-toolkit.tar.gz
tar zxf percona-toolkit-2.2.13.tar.gz
cd percona-toolkit-2.2.13
perl Makefile.PL
make && make install

3.master与slave数据库创建以及用户授权

Create database pt CHARACTER SET utf8;
GRANT UPDATE,INSERT,DELETE,SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'backup'@'192.168.100.8' identified by 'abc123';
GRANT ALL ON pt.* TO 'backup'@'192.168.100.8' IDENTIFIED BY 'abc123';
flush privileges;


use pt;
CREATE TABLE IF NOT EXISTS 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 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (db, tbl, chunk),
INDEX ts_db_tbl (ts, db, tbl)
) ENGINE=InnoDB;

4.进行校验 master上执行

pt-table-checksum --nocheck-binlog-format --nocheck-plan --nocheck-replication-filters --replicate=pt.checksums --set-vars innodb_lock_wait_timeout=120 --databases tmp -u'backup' -p'abc123' -h192.168.100.8 -P3306

#-h -u -p -P -S -d 连接信息 
#--nocheck-replication-filters 检测中忽略mysql 配置参数binlog_ignore_db等。
#--nocheck-binlog-format 不检测日志格式 
#--replicate 指定checksum 存储的db和表, 如pt.checksum 
# --chunk-size, --chunk-size-limit 用于指定检测块的大小。 可控性更强 
# --ignore-databases/tables/column 跳出指定元素的过滤 
# --lock-wait-timeout innodb 锁的超时设定, 默认为1 
# --max-load 设置最大并发连接数 
# --replicate-check-only 只输出数据不一致的信息。 
# --help 

校验结果

# A software update is available: 
# * The current version for Percona::Toolkit is 2.2.14. 

TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE 
07-21T12:21:59 0 0 3523 4 0 0.385 tmp.COMM_REGION 
07-21T12:21:59 0 0 0 1 0 0.011 tmp.UCT_USER
07-21T12:22:04 0 0 115020 1 0 5.007 tmp.UCT_USER_1 
07-21T12:22:04 0 0 0 1 0 0.017 tmp.UCT_USER_2 
07-21T12:22:04 0 0 710 1 0 0.009 tmp.VOX_APPLICATION_MICROPHONE
07-21T12:22:04 0 0 3778 1 0 0.084 tmp.VOX_CLASS 

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

注意:
要是在执行命令的过程遇到找不到从服务器的错误: 

Diffs cannot be detected because no slaves were found. Please read the --recursion-method documentation for information.

默认是通过show processlist 找到host的值或show slave hosts 找到host的值。

关于--recursion-method参数的设置有:
METHOD USES
=========== =============================================
processlist SHOW PROCESSLIST
hosts SHOW SLAVE HOSTS
cluster SHOW STATUS LIKE 'wsrep\_incoming\_addresses'
dsn=DSN DSNs from a table
none Do not find slaves

pt-table-checksum --nocheck-binlog-format --nocheck-plan --nocheck-replication-filters --replicate=pt.checksums --set-vars innodb_lock_wait_timeout=120  --recursion-method dsn=h=10.0.1.73,D=stats,t=dsns -u'backup' -p'abc123' --host=10.0.1.72 -P3306 --databases=HS_Order(校验)

[root@goufu data]# pt-table-sync --print --sync-to-master h=10.0.1.73,P=3306,u=backup,p='abc123' --replicate pt.checksums --databases=HS_Order --tables=VOX_REWARD_ORDER>zzz.sql (也可直接加--execute自动修复)

mysql> show slave hosts;
+-----------+------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+------+------+-----------+--------------------------------------+
| 123305 | | 3305 | 533306 | 9645c4a3-178a-11e6-ac5d-d4ae52d034a7 |
+-----------+------+------+-----------+--------------------------------------+
1 row in set (0.00 sec)

在从库的配置文件里加: 
report_host = 192.168.200.25 #设置成本地地址

mysql> show slave hosts; 
+-----------+----------------+------+-----------+--------------------------------------+
| Server_id | Host | Port | Master_id | Slave_UUID |
+-----------+----------------+------+-----------+--------------------------------------+
| 123305 | 192.168.100.12 | 3305 | 533306 | 9645c4a3-178a-11e6-ac5d-d4ae52d034a7 |
+-----------+----------------+------+-----------+--------------------------------------+

最后再执行以上命令(多加--recursion-method=hosts 参数): 

pt-table-checksum --nocheck-binlog-format --nocheck-plan --nocheck-replication-filters --replicate=pt.checksums --set-vars innodb_lock_wait_timeout=120 --recursion-method=hosts --databases tmp -u'backup' -p'abc123' -h192.168.100.8 -P3306

先校验出哪些库的表不同步,然后指定库与表生成语句,采用第二种方法, 将生成的SQL语句在从库执行即可。
5.数据同步,复制,消除差异(Master服务器运行) 要是有中文的则需要加上:--charset=utf8,防止乱码。

i.自动消除差异(不推荐) 

pt-table-sync --print --execute --sync-to-master h=192.168.100.87,P=3341,u=backup,p='abc123' --databases=test --tables=goufu

ii.打印出sql语句,人工干预到Slave库执行(推荐) 

[root@goufu data]# pt-table-sync --print --sync-to-master h=192.168.100.87,P=3341,u=goufu,p='abc123' --databases=test --tables=goufu
REPLACE INTO `test`.`goufu`(`a`) VALUES ('1') /*percona-toolkit src_db:test src_tbl:goufu
src_dsn:P=3340,h=192.168.100.87,p=...,u=goufu dst_db:test dst_tbl:goufu dst_dsn:P=3341,h=192.168.100.87,p=...,u=backup lock:1 transaction:1 changing_src:1 replicate:0 bidirectional:0 pid:7020 user:root host:VM-TEST-87*/; 

pt-table-sync --print --sync-to-master h=10.1.1.7,P=3306,u=backup,p='abc123'--replicate pt.checksums 

#--sync-to-master :指定一个DSN,即从的IP,他会通过show processlist或show slave status 去自动的找主。
#--replicate :指定通过pt-table-checksum得到的表,这2个工具差不多都会一直用。 
#--print :打印,但不执行命令。 
#--execute :执行命令。


7.实际解决:

[root@goufu ~]# pt-table-checksum --nocheck-binlog-format --nocheck-plan --nocheck-replication-filters --replicate=pt.checksums --set-vars innodb_lock_wait_timeout=120 --recursion-method=hosts --databases bbs,HomeworkSitter_UAT --tables=dz_common_session,VOX_VOICE_RECOMMEND_DATA_SENTENCE_REF -u 'backup' -p'goufu' -h192.168.100.8 -P3306

TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
07-21T15:37:03 0 2 106683 4 0 0.588 HomeworkSitter_UAT.VOX_VOICE_RECOMMEND_DATA_SENTENCE_REF
07-21T15:37:03 0 1 3 1 0 0.026 bbs.dz_common_session

由于其中一个表的数据较大,采用dump导出的方式在从库上恢复
1.第一个执行采用pt-table-sync方式恢复

pt-table-sync --print --sync-to-master h=192.168.100.12,P=3305,u=goufu,p='abc123' --databases=bbs --tables=dz_common_session 

2.第二个表采用导出导入的方式恢复

pt-table-sync --print --sync-to-master h=192.168.100.12,P=3305,u=goufu,p='abc123' --databases=bbs --tables=dz_common_session 

同步完成后再校验:

[root@goufu ~]# pt-table-checksum --nocheck-binlog-format --nocheck-plan --nocheck-replication-filters --replicate=pt.checksums --set-vars innodb_lock_wait_timeout=120 --recursion-method=hosts --databases bbs,HomeworkSitter_UAT --tables=dz_common_session,VOX_VOICE_RECOMMEND_DATA_SENTENCE_REF -u'backup' -p'abc123' -h192.168.100.8 -P3306
TS ERRORS DIFFS ROWS CHUNKS SKIPPED TIME TABLE
07-21T16:50:19 0 0 106683 5 0 1.006 HomeworkSitter_UAT.VOX_VOICE_RECOMMEND_DATA_SENTENCE_REF
07-21T16:50:19 0 0 3 1 0 0.013 bbs.dz_common_session

注意事项

1.采用replace into来修复主从不一致,必须保证被replace的表上有主键或唯一键,否则replace into退化成insert into,起不到修复的效果。这种情况下pt-table-sync会采用其他校验和修复算法,但是效率非常低,例如对所有列的group by然后求count(*)(表一定要有主键!)。

2.主从数据不一致需要通过replace into来修复,该sql语句必须是语句级。pt-table-sync会把它发起的所有sql语句都设置为statement格式,而不管全局的binlog_format值。这在级联A-B-C结构中,也会遇到pt-table-checksum曾经遇到的问题,引起行格式的中继库的从库卡库是必然。不过pt-table-sync默认会无限递归的对从库的binlog格式进行检查并警告。

3.由于pt-table-sync每次只能修复一个表,所以如果修复的是父表,则可能导致子表数据连带被修复,这可能会修复一个不一致而引入另一个不一致;如果表上有触发器,也可能遇到同样问题。所以在有触发器和主外键约束的情况下要慎用。pt-table-sync工具同样也不欢迎主从异构的结构。pt-table-sync工具默认会进行先决条件的检查。

4.pt-table-sync在修复过程中不能容忍从库延迟,这正好与pt-table-checksum相反。如果从库延迟太多,pt-table-sync会长期持有对chunk的for update锁,然后等待从库的master_pos_wait执行完毕或超时。从库延迟越大,等待过程就越长,主库加锁的时间就越长,对线上影响就越大。因此要严格设置max-lag。

5.对从库数据的修复通常是在主库执行sql来同步到从库。因此,在有多个从库时,修复某个从库的数据实际会把修复语句同步到所有从库。数据修复的代价取决于从库与主库不一致的程度,如果某从库数据与主库非常不一致,举例说,这个从库只有表结构,那么需要把主库的所有数据重新灌一遍,然后通过binlog同步,同时会传递到所有从库。这会给线上带来很大压力,甚至拖垮集群。正确的做法是,先用pt-table-checksum校验一遍,确定不一致的程度:如果不同步的很少,用pt-table-sync直接修复;否则,用备份先替换它,然后用pt-table-sync修复。 说明: 这实际提供了一种对myisam备份的思路:如果仅有一个myisam的主库,要为其增加从库,则可以:先mysqldump出表结构到从库上,然后启动同步,然后用pt-table-sync来修复数据。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
25天前
|
关系型数据库 MySQL Shell
MySQL 备份 Shell 脚本:支持远程同步与阿里云 OSS 备份
一款自动化 MySQL 备份 Shell 脚本,支持本地存储、远程服务器同步(SSH+rsync)、阿里云 OSS 备份,并自动清理过期备份。适用于数据库管理员和开发者,帮助确保数据安全。
|
11天前
|
关系型数据库 MySQL Linux
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
82 28
|
1月前
|
存储 SQL 关系型数据库
【YashanDB知识库】MySQL迁移至崖山char类型数据自动补空格问题
**简介**:在MySQL迁移到崖山环境时,若字段类型为char(2),而应用存储的数据仅为'0'或'1',查询时崖山会自动补空格。原因是mysql的sql_mode可能启用了PAD_CHAR_TO_FULL_LENGTH模式,导致保留CHAR类型尾随空格。解决方法是与应用确认数据需求,可将崖山环境中的char类型改为varchar类型以规避补空格问题,适用于所有版本。
|
30天前
|
SQL 关系型数据库 MySQL
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
本文探讨了在使用YMP 23.2.1.3迁移MySQL Server字符集为latin1的中文数据至YashanDB时出现乱码的问题。问题根源在于MySQL latin1字符集存放的是实际utf8编码的数据,而YMP尚未支持此类场景。文章提供了两种解决方法:一是通过DBeaver直接迁移表数据;二是将MySQL表数据转换为Insert语句后手动插入YashanDB。同时指出,这两种方法适合单张表迁移,多表迁移可能存在兼容性问题,建议对问题表单独处理。
【YashanDB知识库】字符集latin1的MySQL中文数据如何迁移到YashanDB
|
1月前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致 2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中 这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中 1. 使用MQ异步同步, 保证数据的最终一致性 我们项目中会根据业务情况 , 使用不同的方案来解决Redis和Mysql的一致性问题 : 1. 对于一些一致性要求不高的场景 , 不做处理例如 : 用户行为数据 ,
|
2月前
|
SQL 关系型数据库 MySQL
基于SQL Server / MySQL进行百万条数据过滤优化方案
对百万级别数据进行高效过滤查询,需要综合使用索引、查询优化、表分区、统计信息和视图等技术手段。通过合理的数据库设计和查询优化,可以显著提升查询性能,确保系统的高效稳定运行。
85 9
|
2月前
|
监控 关系型数据库 MySQL
MySQL和SQLSugar百万条数据查询分页优化
在面对百万条数据的查询时,优化MySQL和SQLSugar的分页性能是非常重要的。通过合理使用索引、调整查询语句、使用缓存以及采用高效的分页策略,可以显著提高查询效率。本文介绍的技巧和方法,可以为开发人员在数据处理和查询优化中提供有效的指导,提升系统的性能和用户体验。掌握这些技巧后,您可以在处理海量数据时更加游刃有余。
240 9
|
2月前
|
存储 SQL 关系型数据库
【YashanDB 知识库】MySQL 迁移至崖山 char 类型数据自动补空格问题
问题分类】功能使用 【关键字】char,char(1) 【问题描述】MySQL 迁移至崖山环境,字段类型源端和目标端都为 char(2),但应用存储的数据为'0'、'1',此时崖山查询该表字段时会自动补充空格 【问题原因分析】mysql 有 sql_mode 控制,检查是否启用了 PAD_CHAR_TO_FULL_LENGTH SQL 模式。如果启用了这个模式,MySQL 才会保留 CHAR 类型字段的尾随空格,默认没有启动。 #查看sql_mode mysql> SHOW VARIABLES LIKE 'sql_mode'; 【解决/规避方法】与应用确认存储的数据,正确定义数据
|
1月前
|
关系型数据库 MySQL Java
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
【YashanDB知识库】原生mysql驱动配置连接崖山数据库
|
1月前
|
关系型数据库 MySQL 数据库连接
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
302 82
下一篇
oss创建bucket