相信很多人的线上都搭建了MySQL主从这样的框架,很多人只监控MySQL的从服务器Slave_IO和Slave_SQL这两个线程是否为YES,还有 Seconds_Behind_Master延迟大不大之类的一些信息。但他们是否定期的去检查MySQL主服务器的数据和从服务器的数据是否一致呢,数据一致性才是最重要的,有人很好奇的问,如果数据不一致,就肯定没有两个YES的出现啦,我想说,不一定的,因为当slave出现错误时,可以通过SET GLOBAL sql_slave_skip_counter = N来跳过错误,还有可以通过选项--slave-skip-errors=[error_code]来跳过错误代码,这样处理后Slave_IO和Slave_SQL状态依然为YES,但这个时候,数据可能就跟主库不一致了。下面和大家学习一个很不错的工具pt-table-checksum

pt-table-checksum:MySQL复制完整性校验(这个工具的重点是找到有效数据的差异。如果任何数据是不同的,你可以用pt-table-sync解决问题。)

软件包下载地址:http://www.percona.com/downloads/percona-toolkit/2.2.7/RPM/percona-toolkit-2.2.7-1.noarch.rpm

PT工具的安装,可以参考我的博客:http://www.cnblogs.com/xuanzhi201111/p/4128894.html(主库和从库都要安装)

实验环境:   master(192.168.1.128:3306)

slave(192.168.1.129:3306)

注意事项:

1、  根据测试,需要一个即能登录主库,也能登录从库的账号;

2、  只能指定一个host,必须为主库的IP;

3、  在检查时会向表加S锁;

4、  如果master和slave的binlog日志不是STATEMENT格式,要用--no-check-binlog-format选项

5、  运行之前需要从库的同步IO和SQL进程是YES状态。

6、  表要有主键索引或唯一键索引

在主库上(master:3306),如下:

mysql> select * from check_sum.test1;
+------+-------+
| id   | couse |
+------+-------+
|    1 | aa    |
|    2 | bb    |
|    3 | cc    |
+------+-------+
3 rows in set (0.00 sec)mysql> 

在从库(slave:3306),如下(跟master数据不一致了):

mysql> select * from check_sum.test1;
+------+-------+
| id   | couse |
+------+-------+
|    1 | aa    |
|    2 | bb    |
+------+-------+
2 rows in set (0.00 sec)mysql> 

pt-table-checksum参数解释:

--nocheck-replication-filters :不检查复制过滤器,建议启用。后面可以用--databases来指定需要检查的数据库。
--no-check-binlog-format      : 不检查复制的binlog模式,要是binlog模式是ROW,则会报错。
--replicate-check-only :只显示不同步的信息。
--replicate=    :把checksum的信息写入到指定表中,建议直接写到被检查的数据库当中。
--databases=    :指定需要被检查的数据库,多个则用逗号隔开。
--tables=       :指定需要被检查的表,多个用逗号隔开
h=192.168.1.128 :Master的地址
u=root          :用户名
p=123456        :密码
P=3306          :端口

在主库上执行数据检查命令:

[root ~]$ pt-table-checksum  --nocheck-replication-filters --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306
Replica slave has binlog_format MIXED 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.

上面报错了,意思说如果binlog_format 为MIXED格式,会破坏同步,可以使用--no-check-binlog-format选项来关闭检查

添加上--no-check-binlog-format选项,再在master库上执行,报以下错(标红的为报错信息):

[root ~]$ pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format  --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306
Cannot connect to P=3306,h=192.168.1.129,p=...,u=root
Diffs cannot be detected because no slaves were found.  Please read the --recursion-method documentation for information.TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
04-13T15:44:23      0      0        3       1       0   0.044 check_sum.test1

上面已经告诉你怎么做了, Please read the --recursion-method documentation for information,上面的提示信息很清楚,因为找不到slave库,所以执行失败。用参数--recursion-method 可以指定模式解决,关于--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

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

*************************** 1. row ***************************Id: 7User: adminHost: 192.168.1.129:60195db: NULL
Command: Binlog DumpTime: 663201State: Master has sent all binlog to slave; waiting for binlog to be updatedInfo: NULL
*************************** 2. row ***************************Id: 37User: rootHost: localhostdb: check_sum
Command: QueryTime: 0State: NULLInfo: show processlist
4 rows in set (0.00 sec)

还有一种方法是show slave hosts;前提从库配置文件里面已经配置自己的地址和端口,在slave库上操作(在[mysqld]下添加这两行):

[root mysql-5.5.40]$ cat  my.cnf |grep "report"
report_host=192.168.1.129
report_port=3306

回到master库操作:

mysql> show slave hosts;
+-----------+---------------+------+-----------+
| Server_id | Host          | Port | Master_id |
+-----------+---------------+------+-----------+
|        11 | 192.168.1.129 | 3306 |         1 |
+-----------+---------------+------+-----------+
1 row in set (0.00 sec)mysql> 

最重要的一点是我们需要在从库上授权,能让主库访问,只能指定一个host,必须为主库的IP,在slave库上操作;

mysql>GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'admin'@'192.168.1.128' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)mysql> flush privileges;Query OK, 0 rows affected (0.00 sec)mysql> 

如果在master没有让admin用户登录的权利,要在master库给admin权限,很多人用root用户来检查,所以只要在从库权限即可(在master库上操作):

mysql>GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'admin'@'192.168.1.128' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> 

权限解释:

select     //查看所有库的表,原理可加 explain选项查看
process    //show processlist
super      //set binlog_format='statement'
replication slave   //show slave hosts

现在我们再来检测数据一致性(master库上操作):

[root ~]$ pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306  TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
12-26T15:38:30      0      1        3       1       0   0.339 check_sum.test1

看到已经检查出主从数据有不一致了,DIFFS下的值为1,怎么不一致呢? 通过指定--replicate=test.checksums 参数,就说明把检查信息都写到了checksums表中

下面对例的含义进行解释:

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

之前一直以为去master的test.checksums表查看主库与从库不一致的信息,纠结了N久,前面显示了DIFFS下的值为1,但master上看表里的信息如下:

mysql> select * from test.checksums\G
*************************** 1. row ***************************db: check_sumtbl: test1chunk: 1chunk_time: 0.023619chunk_index: NULL
lower_boundary: NULL
upper_boundary: NULLthis_crc: d5b7731c   #slavethis_cnt: 3               #slavemaster_crc: d5b7731c  #mastermaster_cnt: 3              #master
            ts: 2014-12-26 15:50:29
1 row in set (0.00 sec)mysql> 

看到了吧,它们信息一样,正常来说,表里信息应该是master跟slave不一致才对的,现在是一致,如果test.checksum里的对比是一样的,是不能把slave库少了的数据从master库同步过去的,因为pt-table-sync同步数据时,要借助test.checksum表。别急:我们再去看一下slave库下的test.checksums:(slave库操作)

mysql> select * from test.checksums\G
*************************** 1. row ***************************db: check_sumtbl: test1chunk: 1chunk_time: 0.023619chunk_index: NULL
lower_boundary: NULL
upper_boundary: NULLthis_crc: 64fdcfa3this_cnt: 2       #slave 2行数据    master_crc: d5b7731cmaster_cnt: 3      #master 3行数据ts: 2014-12-26 15:50:29
1 row in set (0.00 sec)

在master库可以可以用--print选项打印出master下的check_sum.test1和slave库的check_sum.test1的不一致的数据,如下:

[root ~]$  pt-table-sync --replicate=test.checksums h=192.168.1.128,u=admin,p=123456,P=3306 h=192.168.1.129,u=admin,p=123456,P=3306 --print
Can't make changes on the master because no unique index exists at /usr/bin/pt-table-sync line 10648.  while doing check_sum.test1 on 192.168.1.129

以上报错了,报错信息也很明显,说表没有唯一索引,在master库上给表添加主键索引或者唯一索引:

mysql> alter table test1 add primary key (id);
Query OK, 3 rows affected (0.17 sec)
Records: 3  Duplicates: 0  Warnings: 0mysql> show create table test1\G
*************************** 1. row ***************************Table: test1
Create Table: CREATE TABLE `test1` (`id` int(11) NOT NULL DEFAULT '0',`couse` char(10) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)mysql> 

再在master执行一次pt-table-checksum,再执行pt-table-sync,如下:

[root ~]$ pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
12-26T17:16:50      0      1        3       1       0   0.151 check_sum.test1
[root ~]$ pt-table-sync --replicate=test.checksums h=192.168.1.128,u=admin,p=123456,P=3306 h=192.168.1.129,u=admin,p=123456,P=3306 --print
REPLACE INTO `check_sum`.`test1`(`id`, `couse`) VALUES ('3', 'cc') /*percona-toolkit src_db:check_sum src_tbl:test1 src_dsn:P=3306,h=192.168.1.128,p=...,u=admin dst_db:check_sum dst_tbl:test1 dst_dsn:P=3306,
h=192.168.1.129,p=...,u=admin lock:1 transaction:1 changing_src:test.checksums replicate:test.checksums bidirectional:0 pid:41368 user:root host:localhost.localdomain*/;

大家都看到了有不一致的数据记录了吧

参数说明:

--replicate=    :指定通过pt-table-checksum得到的表.
--databases=    : 指定执行同步的数据库,多个用逗号隔开。
--tables=       :指定执行同步的表,多个用逗号隔开。
--sync-to-master :指定一个DSN,即从的IP,他会通过show processlist或show slave status 去自动的找主。
h=127.0.0.1     :服务器地址,命令里有2个ip,第一次出现的是Master的地址,第2次是Slave的地址。
u=root          :帐号。
p=123456        :密码。
--print         :打印,但不执行命令。
--execute       :执行命令。

接下的操作就是把slave上少的数据,从master同步过去(master操作):

通过(--execute),让它们数据保持一致性:

[root ~]$ pt-table-sync --replicate=test.checksums h=192.168.1.128,u=admin,p=123456,P=3306 h=192.168.1.129,u=admin,p=123456,P=3306 --execute
INSERT,DELETE command denied to user 'admin'@'192.168.1.128' for table 'test1' [for Statement "REPLACE INTO `check_sum`.`test1`(`id`, `couse`) VALUES ('3', 'cc')
/*percona-toolkit src_db:check_sum src_tbl:test1 src_dsn:P=3306,h=192.168.1.128,p=...,u=admin dst_db:check_sum dst_tbl:test1 dst_dsn:P=3306,h=192.168.1.129,p=...,u=admin lock:1 transaction:1
changing_src:test.checksums replicate:test.checksums bidirectional:0 pid:41650 user:root host:localhost.localdomain*/"] at line 10707 while doing check_sum.test1 on 192.168.1.129

看到报错了吧,提示admin用户没有INSERT、DELETE权限(如果是root用户,就没这些小问题),在master授权admin用户权限后再执行如下命令(master操作):

[root ~]$ pt-table-sync --replicate=test.checksums h=192.168.1.128,u=admin,p=123456,P=3306 h=192.168.1.129,u=admin,p=123456,P=3306 --execute

[root ~]$ pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306 TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
12-26T17:57:18      0      0        3       1       0   0.073 check_sum.test1

可以看到再次检查的时候,DIFFS已经是0了,去slave查看一下表的数据(slave操作):

mysql> select * from check_sum.test1;
+----+-------+
| id | couse |
+----+-------+
|  1 | aa    |
|  2 | bb    |
|  3 | cc    |
+----+-------+
3 rows in set (0.00 sec)

已经跟master上的数据一致了。

第二种情况:(slave的端口不是3306,则要用另一种方式去检查)

环境:192.168.1.128:3306(master)

192.168.1.129:3307(slave)

执行数据检查命令pt-table-checksum:

[root ~]$  pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306
Cannot connect to P=3306,h=192.168.1.129,p=...,u=admin
Diffs cannot be detected because no slaves were found.  Please read the --recursion-method documentation for information.TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
12-26T19:59:11      0      0        3       1       0   0.065 check_sum.test1

以上报错了,因为pt-table-checksum默认是找slave库的3306,现在slave上的端口是3307了(在master操作):

mysql> show slave hosts;
+-----------+---------------+------+-----------+
| Server_id | Host          | Port | Master_id |
+-----------+---------------+------+-----------+
|        11 | 192.168.1.129 | 3307 |         1 |
+-----------+---------------+------+-----------+
1 row in set (0.00 sec)mysql> 

在master上test库上创建一个表:

mysql> use test
Database changed
mysql> CREATE TABLE `dsns` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULT NULL, `dsn` varchar(255) NOT NULL, PRIMARY KEY (`id`) );
Query OK, 0 rows affected (0.08 sec)
mysql> 

写入从库信息,如果有多个从库,就插入多条记录:

mysql> INSERT INTO dsns (parent_id,dsn) values(1, "h=192.168.1.129,u=admin,p=123456,P=3307");
Query OK, 1 row affected (0.04 sec)mysql> select * from dsns;
+----+-----------+-----------------------------------------+
| id | parent_id | dsn                                     |
+----+-----------+-----------------------------------------+
|  1 |         1 | h=192.168.1.129,u=admin,p=123456,P=3307 |
+----+-----------+-----------------------------------------+
1 row in set (0.00 sec)

然后在master上执行数据校验命令:

[root ~]$  pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306--recursion-method=dsn=h=192.168.1.128,D=test,t=dsns             TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
12-26T20:10:30      0      0        3       1       0   0.100 check_sum.test1

在slave库执行删除数据操作:

mysql> select * from test1;
+----+-------+
| id | couse |
+----+-------+
|  1 | aa    |
|  2 | bb    |
|  3 | cc    |
+----+-------+
3 rows in set (0.00 sec)mysql> delete from test1 where id=3;
Query OK, 1 row affected (0.00 sec)

再在master库执行数据校验命令:

[root ~]$  pt-table-checksum  --nocheck-replication-filters --no-check-binlog-format --replicate=test.checksums --databases=check_sum  h=192.168.1.128,u=admin,p=123456,P=3306 --recursion-method=dsn=h=192.168.1.128,
D=test,t=dsnsTS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
12-26T20:25:42      0      1        3       1       0   0.020 check_sum.test1

已经检查出数据不一致了,至于怎么把数据同步到从库,还没研究出来,按第一种方法,再换一下端口,也不行,因为pt-table-sync默认找3306端口,如果你研究出来了,分享下哈,哈哈^.^

总结pt-table-checksum和pt-table-sync工具是非常好用的数据检查及修复的工具,在日常生活中会经常用到,可以写脚本去监控数据的一致性

参考资料:http://www.percona.com/doc/percona-toolkit/2.2/pt-table-checksum.html

              http://www.percona.com/doc/percona-toolkit/2.2/pt-table-sync.html

http://keithlan.github.io/2016/05/25/pt_table_checksum/

作者:陆炫志

出处:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111

您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。

转载于:https://www.cnblogs.com/xuanzhi201111/p/4180638.html

利用pt-table-checksum校验数据一致性相关推荐

  1. 技术分享 | 两个单机 MySQL 该如何校验数据一致性

    作者:莫善 某互联网公司高级 DBA. 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源. 需求介绍 业务有两个 MySQL 集群是通过 MQ 进行同步 ...

  2. Hadoop数据完整性与CheckSum校验原理

    一.HDFS数据完整性 用户肯定都希望系统在存储和处理数据时,数据不会有任何丢失或损坏.但是,受网络不稳定.硬件损坏等因素,IO操作过程中难免会出现数据丢失或脏数据,难免会出现数据丢失或脏数据,数据传 ...

  3. 利用PT模拟器设计的小型企业局域网实验

    利用PT模拟器设计的小型企业局域网实验 小型企业拓扑图 第一步:规划ip地址,已经规划好了 分别分成192.168.1.10/24192.168.2.10/24192.168.3.10/24这是PC机 ...

  4. 利用mk-table-checksum监测Mysql主从数据一致性操作记录

    前面已经提到了mysql主从环境下数据一致性检查:mysql主从同步(3)-percona-toolkit工具(数据一致性监测.延迟监控)使用梳理 今天这里再介绍另一种Mysql数据一致性自动检测工具 ...

  5. android checksum校验

    checksum就是校验码,和md5的概念可以说是一样的,只是算法不一样. checksum的算法也都不一样,看定的协议是怎么样的 我这边的业务场景是需要android端给打印机发送一个升级指令,两个 ...

  6. checksum校验

    原理 P/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,采用的都是将数据流视为16位整数流进行重复叠加计算.为了计算检验和,首先把检验和字段置为0.然后,对有效数据范围内中每个16位 ...

  7. SQL SERVER数据页checksum校验算法

    在SQL SERVER2005以上版本中,数据页默认开启checksum,标识为m_flagBits & 0x200 == True,其值m_tornBits位于页头0x3C,4字节. 其算法 ...

  8. java数据校验博客_springmvc教程:利用Validation进行参数校验

    上传图片 1.1 配置虚拟目录 1.2 配置解析器 Validation校验 b/s系统中对http请求数据的校验多数在客户端进行,这也是出于简单及用户体验性上考虑,但是在一些安全性要求高的系统中服务 ...

  9. spring入参为指定值,校验java入参的值为规定的值,利用Validator指定值校验注解——一看就会

    我们在使用spring项目的时候,经常使用@Valid来对入参进行校验,比如必须为空,必须不为空,长度多少,是否符合邮件格式等等,同时也可以正则. 如下图所示, @Null(message = &qu ...

  10. html表格图片垂直居中 css,利用Display: table;实现img图片垂直居中

    html代码: CSS代码: .tablebox{width: 300px;height: 250px;bac公斤round: #fff;display: table} #imgbox{display ...

最新文章

  1. python codecs.open()及文件操作-文本处理 with open
  2. The form contains the following errors
  3. 科大星云诗社动态20210427
  4. 最简单的一个java驱动jdbc链接mysql数据库
  5. Git代码管理常用命令操作
  6. android app逆向分析,如何开始对Android应用的逆向分析?
  7. 优秀!33岁博士,拟作为县长人选!
  8. LANC环链电动葫芦的结构设计与组成
  9. 马哥linux docker视频,[其他] 马哥Docker + K8S 视频教程
  10. C# 微信公众号开发
  11. 相控阵天线均匀面阵方向图(六)-----方向图函数的不同表达形式
  12. 读书百客:《山坡羊·北邙山怀古》赏析
  13. 思科Cisco BGP 专题(一) BGP基本概念
  14. lattice绘图工具
  15. 计算机如何把表格分成两排,wps表格怎么拆分单元格,excel单元格拆分两列
  16. Silvaco TCAD LTPS双栅器件仿真收敛不了,有没有好的解决办法
  17. 树莓派 可用于播放音频的三个软件
  18. 数据库 实验三 数据库查询和数据操纵
  19. PAT-A-1062 Talent and Virtue 【排序】
  20. Lawliet|Python学习笔记——random库

热门文章

  1. php连接postgresql数据库
  2. jquery cookie 插件 (支持json对象) 可以跟jquery 集成 也可以单独使用
  3. NAT地址转换的三种实现方式
  4. Net下的AppDomain编程 [摘录]
  5. 咏南中间件D7客户端演示
  6. socket 关于同一条TCP链接数据包到达顺序的问题
  7. 并发编程 进程基础
  8. VS2017设置C++标准
  9. js学习总结----浏览器滚动条卷去的高度scrolltop
  10. TYVJ 4354 多重背包二进制优化