解决主从复制数据不一致的情况

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介:

主从复制不一致的情况解决:

不一致的原因:
1、 主从切换时,出现的故障
2、 误操作
3、 机器故障等
方法一:利用MySQL原生的mysqldump就可以搞定,对于个别表有锁表的情况。
核心是 mysqldump –single-transaction --master-data=2

       Start slave until MASTER_LOG_FILE=’’, MASTER_LOG_POS=;

       直到sql_thread线程为NO,这之间的同步报错一律跳过即可

方法二:工具:pt-table-sync
有效的同步MySQL 表的数据。

操作前,最好先备份。对于主从结构来讲,它只需要在master上操作即可(无论是 使用的选项是 –reolicate 还是 –sync-to-master)这种方式往往是重新让master和slave保持同步的最安全的方式,直接修改replica可能会带来很多问题。

注意事项; --dry-run 查看该工具用那种算法进行操作。

           --print 如何具体解决主从的不一致的。

           对于主主复制的形式,要相当谨慎。

           当表含有外键,并且是 on delete 或 on update 约束的情况下,建议暂时不用,可能对子表造成意外的破坏。

           部分bug。 --lock-and-rename 对于小于MySQL 5.5 版本的DB是不起作用的(考虑用 pt-online-schema-change 代替?)。

详解:
Pt-table-sync 可以做到对表的数据进行单项或者双向同步。它并不同步表的结构、索引或者其他的数据库对象,仅仅是行记录。
下面先介绍下单向表数据同步

先介绍三个概念: --replicate , find differences , specifying

下面是简短的逻辑:
 
if DSN has a t part, sync only that table:
   if 1 DSN:
      if --sync-to-master:
         The DSN is a slave. Connect to its master and sync.
   if more than 1 DSN:
      The first DSN is the source. Sync each DSN in turn.
else if --replicate:
   if --sync-to-master:
      The DSN is a slave. Connect to its master, find records
      of differences, and fix.
   else:
      The DSN is the master. Find slaves and connect to each,
      find records of differences, and fix.
else:
   if only 1 DSN and --sync-to-master:
      The DSN is a slave. Connect to its master, find tables and
      filter with --databases etc, and sync each table to the master.
   else:
      find tables, filtering with --databases etc, and sync each
      DSN to the first
 

默认情况下, 没有—replicate 选项(该选项使用 几种算法自动发现master和slave之间的不同),另外该选项还能利用 pt-table-checksum 已经检查查来的问题。严格来讲,我们不需要使用 –replicate 选项,因为它可以自动发现表之间数据的不一致。 但人们结合两个工具的原因是: pt-table-checksum 定期的对表数据进行校验,当发现不一致时再用 pt-table-sync进行修复。

如何确定数据同步的方向; 使用 –sync-to-master 或者省略。该选项值需要一个 slave DSN 参数.自动发现该slave的master,并开始于master进行同步。实现的方式 是在 master端 做出改变,通过MySQL 的复制机制让slave与master 重新同步。 注意事项: 如果只有一台slave的 那没有问题,多台slave的话,可能也会受到同样的数据变更。

如果不使用 –sync-to-master 的话,第一个DSN参数则必须是 source host(有且只有一个),,没有 –replicate选项的话,我们必须在写一个 DSN参数作为 destination   host. 可以有多个 destination host Source 和 destination 必须是独立的,不能在同一个复制结构里面。 如果pt-table-sync 检测到目标host是一个同一个复制拓扑里面的slave,工具会报错。因为对数据所做的一些改变是直接写入到 目的 host的,(将修改数据直接写入一个slave ,如果在引用binlog 日志的话,可能会报错。) 或者如果 我们使用 –replicate 选项的话, pt-table-sync 会期望 DSN参数是 master,这样改工具就可以一次性的发现该master所有的slave,并让slave都重新和master进行同步。(--sync-to-master 只更新一个slave)

该工具的 第一个DSN参数 想对于其他的DSN 提供一些默认参数,比如DB 和table,我们可以手动全部写上,或者让工具自动发现。

比如:pt-table-sync --execute h=host1,u=msandbox,p=msandbox h=host2

Host 2 的 DSN参数 继承了 来自 host1 的 u 和 p 的属性。 使用 –explain-hosts 选项可以看到 pt-table-sync 是如何翻译 命令行上的参数的。

输出:

使用 –verbose 的情况,会显示出对每个操作表所做处理的详细信息:

# Syncing h=host1,D=test,t=test1
# DELETE REPLACE INSERT UPDATE ALGORITHM START    END      EXIT DATABASE.TABLE
#      0       0      3      0 Chunk     13:00:00 13:00:17 2    test.test1

Host1 上的 test db 中的test1 表被插入3条记录。并且使用的算法是 chunk, 时间从13:00:00开始持续了17秒。因为发现master和slave之间的不同,所以退出状态时2 。

复制 安全

一般情况下,最安全的方式是只在master端做出变更,利用mysql的复制机制来达到同步的目的。 前提是 在master端执行的是replace语句,而且表中必须有unique index . 否则的话,只是 原始的 insert 语句,可能有的slave 会出现重复信息。

如果表含有unique keys, 我们可以很轻松的 使用 –sync-to-master 或者 –replicate 选项,如果没有的话,我们只能在slave端进行操作。and pt-table-sync will detect that you’re trying to do so. It will complain and die unless you specify --no-check-slave (see --[no]check-slave).

如果在双主模式下的表中没有主键或者unique key,我们必须在目的主机进行操作。 所以呢,我们需要使用 –no-bin-log 选项。

在双主模式下,一般使用—sync –to-master 参数, You will also need to specify --no-check-slave to keep pt-table-sync from complaining that it is changing data on a slave.

 
pt-table-sync  的算法:

有一个多种算法来发现数据差异的框架,该工具自动选择最合适的算法,依据是表的索引,字段类型和算法的偏好设置。

chunk  算法:
找一个索引中第一个字段为整数型的索引( date time 类型也算),让后根据该索引中的值分解为多个 chunk ,每次通过 checksum  完整的 chunk 来并同步该 chunk 中的数据。如果某个 chunk  checksum  中的值在 source   destination 端不同,那么他会逐个的发现是哪些数据记录出现了问题。
如果有足够的基数就可以高效的为每个 chunk 设置合适的 size (行记录)。
在最初的对每个 chunk 进行  checksum 的时候校验值是相当的小,而且几乎不会浪费网络和内存的资源。在校验的时候,只有 primary key 和一个 checksum 在网络中传输,并不是整个 row ,如果发现某个 row source destination  不一致,这个时候才会取出整条记录。
如果某个字段是 char 类型的并且开始字母都相同,那么该算法就不会起作用,该工具就会退出并提示选择其他的算法。
 
Nibble 算法:

找到一个索引上升指数在固定大小的半字节 - chunk-size行,使用non-backtracking算法,它和chunk算法很类似,但是它不是跟觉表中索引的基数来确定chunk size的大小,而是使用LIMIT定义每个半字节的上限,和之前半字节的上限定义的下限。

它工作的步骤是:查询出一行记录,并且该记录可以定义下一个  nibble 的上限? 下一个  checksum  查询会校验整个 nibble 如果发现源端和目的端有差异,那么它会逐行比较。
 
GroupBy
该算法主要用于没有 primary key 或者  unique index 的情况。选择整个表,并对所有的字段进行排序,并使用 count(*)  计算出行数,比较所有列,如果他们是一样的,比较 COUNT * )列的值,以确定有多少行插入或删除的目标。
 
Stream
选择整个表格并放在一个大的数据流中,比较所有列。选择所有列的效率远低于其他算法,
 
双向同步:现在还处于试验阶段, 所以我们不做过多介绍,只谈谈该功能面临的困难:

1、不适用于 复制架构,只能同步到一台独立的server

2、只能使用chunk 算法,即表中必须有primary key 或者unique key
3、一次只能让两台机器之间同步数据
4、对于delete删除的数据,不能同步。!
 
选项:

至少使用以下选项: --print , --execute, 或者 –dry-run

--where 和 –replicate 是互相排斥的。

--algorithms :默认是 chunk .Nibble ,GroupBy ,Stream
              算法是用来比较表之间的不同,按顺序排列
--[no]bin-log 默认:yes 会控制会话级别变量: SQL_LOG_BIN=1/0

--buffer-in-mysql  该选项对于使用 GroupBy 和 Stream算法的时候,即 表没有primary key                     unique key 的时候特别有效。它开启MySQL SQL_BUFFER_RESULT 选项,

                  MySQL 会对查询的结果放到内存或者临时表里面。好处是:对于使用太多的    

                  Perl 程序使用太多的语言。但是由于MySQL的缓存的查询结果,也不会节省太多内存

--[no]buffer-to-client   默认 :yes 对于MySQLrow记录时 是一条一条对比。

                  该选项开启了MySQL mysql_use_result 选项,当该工具从MySQL获取到该数据的时候,MySQL将不在持有该数据。如果禁用该选项的话,MySQL会一次性发送所有的rows,所以呢,对于大表来说,你可能会禁用改选项

 
--charset 设置默认连接的字符集,

--[no]check-master 默认是 yes, 当使用 –sync-to-master  检测master是否是真正的master

--[no]check-slave 默认是yes:检测目标主机是否是一个slave 。如果直接在slave上操作时很危险的,会造成数据的不一致。
--[no]check-triggers 检测目标表 是否有触发器。
--chunk-column 根据指定的column来 对表 chunk

--chunk-index 根据指定的索引 对表进行chunk

--chunk-size 多少行记录,或者多大的size为一个chunk 。 参数为 K? M? G?数据的大小初一行的平均大小,可以得到行数
--columns  参数用逗号相隔,指定用来比较的columns
--config 读取配置文件,该选项必须设置为第一个参数。
--dry-run  分析、检测、的同步算法和具体实施过程
 
--engines  参数逗号相隔,只同步参数中含有的存储引擎

--execute 具体的去修改表数据。 结合-verbose 选项,我们可以看到执行过程。默认是在安静模式下进行的。

--float-precision FLOAT和DOUBLE数字到字符串的转换精度为。FLOAT和DOUBLE值被舍入到小数点后的指定位数的数字,在MySQL中使用ROUND()函数。这有助于避免由于不同的浮点表示相同的值在不同的MySQL版本和硬件的校验和不匹配。默认情况下是没有四舍五入; CONCAT()函数的值转换成字符串,和MySQL选择的字符串表示形式。如果你指定一个值,例如,1.008和1.009的值将被调整至1.01,并会进行校验和是相等的
--[no]foreign-key-checks  是否启用外键检查, 在MySQL内部是 set foreign_key_checks=1
--ignore-columns
--ignore-database
--ignore-tables
--ignore-engines
--lock :锁表, 0 none 1 per sync cycle(锁住每个chunk) 3 globallly 

          如果 使用—replicate 或者 –sync-to-master 参数时,slave端 是不会锁表的。

          锁表的时候使用的是 lock tables ,但是如果使用 –transaction 的话,就是在事务开始到提交这一段,开始锁表。

--recursioin-method    processlist 是首选的方法来找到slave
--replace 对于 insert 和 update 语句来说全部替换为 replace
--replicate
--sync-to-master  DSN参数为slave
 
举例:
同步 把主机host1 DB1中的 tb1 同步到 host2上
Pt-table-sync –execute h=host1,D=db,t=tb1 h=host2
 
把host1上的表全部都不到 host2 host3    
Pt-table-sync --execute host1 host2 host3
 
让slave从master端保持一致
Pt-table-sync --execute --sync-to-master slave1
 

解决有pt-table-checksum 产生所有slave 对master的 differ结果

Pt-table-sync --execute --replicate test.checksum master1
 
或者只让slave1得到修复:
Pt-table-sync –execute  --replicate test.checksum --sync-to-master slave1
 
在双主模式下,同步master2 中的损害的 db.tb1 上的数据
Pt-table-sync --execute –sync-to-master h=master2,D=db,t=tb1
 
比如下面这个 就不会成立,因为它会直接修改master2上的数据,并且会传递给master1,

Pt-table-sync --execute h=master1,D=db,t=tb1 master2






本文转自 位鹏飞 51CTO博客,原文链接:http://blog.51cto.com/weipengfei/1073340,如需转载请自行联系原作者

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
SQL 存储 关系型数据库
MySQL主从复制、读写分离
MySQL主从复制、读写分离
186 0
|
19天前
|
NoSQL 算法 Redis
主从复制:多副本
【10月更文挑战第6天】
26 1
|
2月前
|
关系型数据库 MySQL Java
MySQL主从复制实现读写分离
MySQL主从复制(二进制日志)、 Sharding-JDBC实现读写分离
MySQL主从复制实现读写分离
|
3月前
|
消息中间件 存储 缓存
深入理解Redis集群主从复制原理
该文章主要探讨了Redis集群中的主从复制原理,包括为何需要主从复制、配置方法、复制流程以及一些高级特性。
深入理解Redis集群主从复制原理
|
SQL canal 缓存
主从复制原理
MySQL binlog(binary log 即二进制日志文件) 主要记录了 MySQL 数据库中数据的所有变化(数据库执行的所有 DDL 和 DML 语句)。因此,我们根据主库的 MySQL binlog 日志就能够将主库的数据同步到从库中
62 0
主从复制原理
|
SQL cobar 算法
第18章_主从复制(下)
第18章_主从复制
151 0
|
SQL 缓存 NoSQL
第18章_主从复制(上)
第18章_主从复制
195 0
|
负载均衡 数据库
主从复制
主从复制
109 0
|
关系型数据库 MySQL Java
MySQL主从复制+读写分离(二)
MySQL主从复制+读写分离(二)
MySQL主从复制+读写分离(二)
|
SQL 存储 关系型数据库