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

  1. 云栖社区>
  2. 博客>
  3. 正文

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

像教授 2017-11-26 20:23:00 浏览1834
展开阅读全文

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

不一致的原因:
1、 主从切换时,出现的故障
2、 误操作
3、 机器故障等
方法一:利用MySQL原生的mysqldump就可以搞定,对于个别表有锁表的情况。
可以参考:http://hcymysql.blog.51cto.com/5223301/951260
核心是 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 算法:
找一个索引中第一个字段为整数型的索引(datetime类型也算),让后根据该索引中的值分解为多个chunk,每次通过checksum 完整的chunk来并同步该chunk中的数据。如果某个chunk checksum 中的值在source  destination端不同,那么他会逐个的发现是哪些数据记录出现了问题。
如果有足够的基数就可以高效的为每个chunk设置合适的size(行记录)。
在最初的对每个chunk进行 checksum的时候校验值是相当的小,而且几乎不会浪费网络和内存的资源。在校验的时候,只有primary key和一个checksum在网络中传输,并不是整个row,如果发现某个rowsourcedestination 不一致,这个时候才会取出整条记录。
如果某个字段是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,如需转载请自行联系原作者

网友评论

登录后评论
0/500
评论
像教授
+ 关注