问题说明

mysql主从同步时难免出现问题导致数据不一致情况.此时需要手动将主从数据同步.

Maatkit是一个开源的工具包,为mySQL日常管理提供了帮助,它包含很多工具,这里主要说下面两个:

  • mk-table-checksum : 用来检测master和slave上的表结构和数据是否一致的;
  • mk-table-sync : 在主从数据不一致时,用来修复数据的;先主后从有效保证表一致的工具,不必重载从表而能够保证一致。

上面两个perl脚本在运行时都会锁表,表的大小取决于执行的快慢,勿在高峰期间运行,可选择凌晨

安装Maatkit

  1. 安装依赖
# 安装依赖yum install perl-IO-Socket-SSL perl-DBD-MySQL perl-Time-HiRes perl perl-DBI -y

yum install perl-ExtUtils-Embed perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker -y

yum -y install perl-Digest-MD5

  1. 下载maatkit
  • 需要翻墙到官网下载:https://code.google.com/archive/p/maatkit/downloads
  • 百度云盘下载地址:https://pan.baidu.com/s/1c1AufW8 (提取密码:vbi1)
  1. 安装maatkit
# 解压进入目录tar -zvxf maatkit-7540.tar.gz  && cd maatkit-7540 

[root@mysql01 maatkit-7540]# perl Makefile.PLChecking if your kit is complete...
Looks good
Writing Makefile for maatkit# 安装make && make install# 测试查看mk-相关命令[root@mysql01 maatkit-7540]# mk-mk-archiver               mk-duplicate-key-checker  mk-heartbeat              mk-log-player             mk-profile-compact        mk-query-profiler         mk-slave-move             mk-table-sync             mk-variable-advisor       
mk-checksum-filter        mk-error-log              mk-index-usage            mk-merge-mqd-results      mk-purge-logs             mk-show-grants            mk-slave-prefetch         mk-table-usage            mk-visual-explain         
mk-config-diff            mk-fifo-split             mk-kill                   mk-parallel-dump          mk-query-advisor          mk-slave-delay            mk-slave-restart          mk-tcp-model              
mk-deadlock-logger        mk-find                   mk-loadavg                mk-parallel-restore       mk-query-digest           mk-slave-find             mk-table-checksum         mk-upgrade

工具使用

  1. 创建mysql检查帐号
-- 主从服务器上创建只有SELECT权限的帐号mysql> GRANT SELECT ON *.* TO 'data_check'@'%' IDENTIFIED BY '123456';Query OK, 0 rows affected (0.01 sec)
 mysql> flush privileges;Query OK, 0 rows affected (0.01 sec)

  1. 检查一致性
# 第一个h:   填写主库ip# 第一个u:   主库授权的用户名# 第一个p:   主库授权的密码# 第二个h:   填写从库ip# 第二个u:   从库授权的用户名# 第二个p:   从库授权的密码# 大写P:   mysql的端口[root@mysql01 maatkit-7540]# mk-table-checksum h=192.168.41.141,u=data_check,p=123456,P=3306 h=192.168.41.142,u=data_check,p=123456,P=3306DATABASE TABLE        CHUNK HOST           ENGINE      COUNT         CHECKSUM TIME WAIT STAT  LAGtest     t_department     0 192.168.41.141 InnoDB       NULL         83657212    0    0 NULL NULLtest     t_department     0 192.168.41.142 InnoDB       NULL       3344593131    0    0 NULL NULLtest     testttt          0 192.168.41.141 InnoDB       NULL       3722958311    0    0 NULL NULLtest     testttt          0 192.168.41.142 InnoDB       NULL       3722958311    0    0 NULL NULL
DATABASE TABLE                     CHUNK HOST           ENGINE      COUNT         CHECKSUM TIME WAIT STAT  LAG
mysql    columns_priv                  0 192.168.41.141 MyISAM       NULL                0    0    0 NULL NULL
mysql    columns_priv                  0 192.168.41.142 MyISAM       NULL                0    0    0 NULL NULL
mysql    db                            0 192.168.41.141 MyISAM       NULL       2629905140    0    0 NULL NULL
mysql    db                            0 192.168.41.142 MyISAM       NULL       2629905140    0    0 NULL NULL
mysql    engine_cost                   0 192.168.41.141 InnoDB       NULL       2678612005    0    0 NULL NULL...# 参数-d(或者--database) 指定要检查的数据库,多个数据库之间用逗号隔开,如果不加-d,校验的是所有库;# --count    会计算出表的行数[root@mysql01 maatkit-7540]# mk-table-checksum h=192.168.41.141,u=data_check,p=123456,P=3306 h=192.168.41.142,u=data_check,p=123456,P=3306 --count -dtestDATABASE TABLE        CHUNK HOST           ENGINE      COUNT         CHECKSUM TIME WAIT STAT  LAGtest     t_department     0 192.168.41.141 InnoDB         13         5e339d70    0    0 NULL NULLtest     t_department     0 192.168.41.142 InnoDB         13         7a4c9153    0    0 NULL NULLtest     testttt          0 192.168.41.141 InnoDB          8         41db7636    0    0 NULL NULLtest     testttt          0 192.168.41.142 InnoDB          8         41db7636    0    0 NULL NULL# 结果参数说明# DATABASE      检查的库名# TABLE:       检查的库中的表名# CHUNK:       checksum时的近似数值# HOST:        主从MYSQL的地址# ENGINE:      表引擎# COUNT:       表的行数# CHECKSUM:    校验值# TIME:        所用时间# WAIT:        等待时间# STAT:        MASTER_POS_WAIT()返回值# LAG:         slave的延时时间# mk-checksum-filter过滤出不一样的结果[root@mysql01 maatkit-7540]# mk-table-checksum h=192.168.41.141,u=data_check,p=123456,P=3306 h=192.168.41.142,u=data_check,p=123456,P=3306 --count -dtest | mk-checksum-filtertest     t_department     0 192.168.41.141 InnoDB         13         5e339d70    0    0 NULL NULLtest     t_department     0 192.168.41.142 InnoDB         13         7a4c9153    0    0 NULL NULL

  1. 修复主从不同步的数据

mk-table-sync用来修复多个实例之间数据的不一致. mk-table-sync的工作方式是:先一行一行检查主从库的表是否一样,如果哪里不一样,就执行删除,更新,插入等操作,使其达到一致。

由于上面在mk-table-checksum检查时用的data_check只有select权限,权限太小,不能用于mk-table-sync修复数据只用。
所以还需要在主库和从库数据库里创建用于mk-table-sync修复数据之用的账号权限

mysql> GRANT ALL ON *.* to mksync@'%' identified by "123456";Query OK, 0 rows affected (0.01 sec)
 mysql> flush privileges;Query OK, 0 rows affected (0.00 sec)

# 注意:主从数据库表和表结构必须一致,否则会报错!# --print               显示同步需要执行的语句# --execute             执行数据同步# --charset=utf8mb4     设置字符集,避免从库乱码。# --no-check-slave      如果不加这个参数,会提示报错,因为此工具默认不允许在从库上修改数据# -t                    指定同步的表名,多个表时可以在-t后加=号,即-t=tables1,tables2,..# > /root/result        命令后面加上 > /root/result 将结果导出[root@mysql01 maatkit-7540]# mk-table-sync --execute --charset=utf8mb4 --print --no-check-slave --databases test h=192.168.41.141,u=mksync,p=123456,P=3306 h=192.168.41.142,u=mksync,p=123456,P=3306UPDATE `test`.`t_department` SET `department_name`='44', `parent_id`='0', `level`='1', `create_time`='2020-07-28 16:06:24', `update_time`='2020-07-28 16:06:24' WHERE `department_id`='3' LIMIT 1 /*maatkit src_db:test src_tbl:t_department src_dsn:A=utf8mb4,P=3306,h=192.168.41.141,p=...,u=mksync dst_db:test dst_tbl:t_department dst_dsn:A=utf8mb4,P=3306,h=192.168.41.142,p=...,u=mksync lock:0 transaction:1 changing_src:0 replicate:0 bidirectional:0 pid:3869 user:root host:mysql01*/;

# 修复之后检查主从,通过CHECKSUM可以看出,数据已经完全一样了[root@mysql01 maatkit-7540]# mk-table-checksum h=192.168.41.141,u=data_check,p=check@123,P=3306 h=192.168.41.142,u=data_check,p=check@123,P=3306 --count -dtestDATABASE TABLE        CHUNK HOST           ENGINE      COUNT         CHECKSUM TIME WAIT STAT  LAGtest     t_department     0 192.168.41.141 InnoDB         13         5e339d70    0    0 NULL NULLtest     t_department     0 192.168.41.142 InnoDB         13         5e339d70    0    0 NULL NULLtest     testttt          0 192.168.41.141 InnoDB          8         41db7636    0    0 NULL NULLtest     testttt          0 192.168.41.142 InnoDB          8         41db7636    0    0 NULL NULL