MySQL主从同步数据一致性检测工具PT实战

MySQL主从复制状态及数据一致性监测工具

一、percona-toolkit工具介绍

percona-toolkit工具中最主要的三个组件分别是:
1.pt-table-checksum 负责监测mysql主从数据一致性
2.pt-table-sync 负责当主从数据不一致时修复数据,让它们保存数据的一致性
3.pt-heartbeat 负责监控mysql主从同步延迟

二、percona-toolkit工具安装
master端安装percona-toolkit工具

2.1 安装依赖包
[root@master ~]# yum install perl-IO-Socket-SSL perl-DBD-MySQL perl-Time-HiRes perl perl-DBI -y

2.2 安装percona-toolkit
下载url:https://www.percona.com/downloads/percona-release/redhat/

[root@master ~]# wget https://www.percona.com/redir/downloads/percona-release/redhat/0.1-6/percona-release-0.1-6.noarch.rpm
[root@master ~]# yum install percona-release-0.1-6.noarch.rpm

[root@master ~]# yum list | grep percona-toolkit
percona-toolkit.x86_64                    3.2.0-1.el7                    @percona-release-x86_64
percona-toolkit.noarch                    2.2.20-1                       percona-release-noarch
percona-toolkit-debuginfo.x86_64          3.0.13-1.el7                   percona-release-x86_64


[root@master ~]# yum install percona-toolkit -y
如果这一步出现了错误,

The GPG keys listed for the "Percona-Release YUM repository - x86_64" repository are already installed but they are not correct for this package.
Check that the correct key URLs are configured for this repository.

 Failing package is: Percona-Server-shared-56-5.6.45-rel86.1.el7.x86_64
 GPG Keys are configured as: file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Percona

解决办法:
yum update percona-release -y

验证安装是否成功
[root@master ~]# pt-table-checksum --help

三、pt-table-checksum使用
pt-table-checksum 是 Percona-Toolkit的组件之一,用于检测MySQL主、从库的数据是否一致。其原理是在主库执行基于statement的sql语句来生成主库数据块的checksum,把相同的sql语句传递到从库执行,并在从库上计算相同数据块的checksum,最后,比较主从库上相同数据块的checksum值,由此判断主从数据是否一致。检测过程根据唯一索引将表按row切分为块(chunk),以为单位计算,可以避免锁表。检测时会自动判断复制延迟、 master的负载, 超过阀值后会自动将检测暂停,减小对线上服务的影响。
pt-table-checksum 默认情况下可以应对绝大部分场景,官方说,即使上千个库、上万亿的行,它依然可以很好的工作,这源自于设计很简单,一次检查一个表,不需要太多的内存和多余的操作;必要时,pt-table-checksum 会根据服务器负载动态改变 chunk 大小,减少从库的延迟。

为了减少对数据库的干预,pt-table-checksum还会自动侦测并连接到从库,当然如果失败,可以指定--recursion-method选项来告诉从库在哪里。它的易用性还体现在,复制若有延迟,在从库 checksum 会暂停直到赶上主库的计算时间点(也通过选项--设定一个可容忍的延迟最大值,超过这个值也认为不一致)。

为了保证主数据库服务的安全,该工具实现了许多保护措施:
    1)自动设置 innodb_lock_wait_timeout 为1s,避免引起高并发
    2)默认当数据库有25个以上的并发查询时,pt-table-checksum会暂停。可以设置 --max-load 选项来设置这个阀值
    3)当用 Ctrl+C 停止任务后,工具会正常的完成当前 chunk 检测,下次使用 --resume 选项启动可以恢复继续下一个 chunk

pt-table-checksum [tmpIONS] [DSN]
pt-table-checksum:在主(master)上通过执行校验的查询对复制的一致性进行检查,对比主从的校验值,从而产生结果。DSN指向的是主的地址,该工具的退出状态不为零,如果发现有任何差别,或者如果出现任何警告或错误.

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

最重要的一点:
要在主库上授权,能让主库ip访问。这一点不能忘记!(实验证明从库上可以不授权,但最好还是从库也授权)
注意:
1)根据测试,需要一个即能登录主库,也能登录从库的账号;
2)只能指定一个host,必须为主库的IP;
3)在检查时会向表加S锁;
4)运行之前需要从库的同步IO和SQL进程是YES状态。

本次实验:
mysql-master:10.12.237.75
mysql-slave:10.12.237.69

4.1 在主库执行授权(一定要对主库ip授权,授权的用户名和密码可自行定义,要保证这个权限能同时登陆主库和从库)
mysql> grant select,process,super,replication slave,create,delete,insert,update on *.* to 'pt'@'10.12.237.75' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

4.2 在两个从库上执行授权
mysql> grant select,process,super,replication slave on *.* to 'pt'@'10.12.237.75' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

4.3 在主库上执行的一个检查主从数据一致性的命令

第一次运行(针对全库):
[root@master ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=pt.checksums --create-replicate-table h=10.12.237.75,u=pt,p=123456,P=3306
注意:第一次运行的时候需要添加--create-replicate-table参数会生成checksums表,如果不加这个参数,那么就需要在对应库下手工添加这张表
#手动添加checksums的表结构SQL如下:
#CREATE TABLE 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,
   PRIMARY KEY (db, tbl, chunk),
   INDEX ts_db_tbl (ts, db, tbl)
#) ENGINE=InnoDB;

第二次运行(针对全库):
[root@master ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=pt.checksums h=10.12.237.75,u=pt,p=123456,P=3306 

#示例一:对特定表的一致性进行检查
pt-table-checksum h=10.12.237.75,u=pt,p=123456,P=3306 --recursion-method=processlist --replicate=pt.checksums --no-check-binlog-format --tables='dbname.tb1,dbname2.tb2'
#示例二:对特定数据库的一致性进行检查
pt-table-checksum h=10.12.237.75,u=pt,p=123456,P=3306 --recursion-method=processlist --replicate=pt.checksums --no-check-binlog-format --databases='dbname1,dbname2'
#示例三:对所有数据库的一致性进行检查
pt-table-checksum h=10.12.237.75,u=pt,p=123456,P=3306 --recursion-method=processlist --replicate=pt.checksums --no-check-binlog-format


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

4.4 扩展:
只显示不同步的信息,打印出来(--replicate-check-only)
[root@master ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate-check-only --replicate=pt.checksums h=10.12.237.75,u=pt,p=123456,P=3306
Checking if all tables can be checksummed ...
Starting checksum ...
Differences on slave
TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY
db1.t4 1 -1 1  

四、pt-table-sync使用

pt-table-sync: 高效的同步MySQL表之间的数据,他可以做单向和双向同步的表数据。他可以同步单个表,也可以同步整个库。它不同步表结构、索引、或任何其他模式对象。所以在修复一致性之前需要保证他们表存在。

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

例如检查数据时发现主从不一致
[root@master ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=pt.checksums --databases=db1 h=10.12.237.75,u=pt,p=123456,P=3306
Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  DIFF_ROWS  CHUNKS SKIPPED    TIME TABLE
07-27T13:41:26      0      0        1          0       1       0   0.013 db1.t1
07-27T13:41:26      0      0        1          0       1       0   0.015 db1.t2
07-27T13:41:26      0      1        3          1       1       0   0.017 db1.t4

现在需要DIFFS为1可知主从数据不一致,需要修复!修复命令如下:(先master的ip,用户,密码,然后是slave的ip,用户,密码)
[root@master ~]# pt-table-sync --execute --print --replicate=pt.checksums h='10.12.237.75',u='pt',p='123456' h='10.12.237.69',u='pt',p='123456'
#pt-table-sync --execute --replicate=pt.checksums h=10.12.237.75,u=pt,p=123456 h=10.12.237.69,u=pt,p=123456  --databases='db1'
 
建议:
1.修复数据的时候,用--print打印出来,这样就可以知道那些数据有问题
2.修复数据之前一定要备份数据库

在上面的操作中,在主库里添加pt-table-checksum检查的权限后,进行数据一致性检查操作,会在操作的库(实例中是pt)下产生一个checksums表!
这张checksums表是pt-table-checksum检查过程中产生的。这张表一旦产生了,默认是删除不了的,并且这张表所在的库也默认删除不了,删除后过一会儿就又会出来。

删除checksums表
主库执行:
mysql> show grants for 'pt'@'10.12.237.75';
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Grants for [email protected]                                                                                                                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'pt'@'10.12.237.75' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> revoke SELECT, INSERT, UPDATE, DELETE, CREATE, PROCESS, SUPER, REPLICATION SLAVE ON *.* FROM 'pt'@'10.12.237.75';
Query OK, 0 rows affected (0.00 sec)

mysql> show grants for 'pt'@'10.12.237.75';
+-------------------------------------------------------------------------------------------------------------------+
| Grants for [email protected]                                                                                   |
+-------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'pt'@'10.12.237.75' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
+-------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select user,host,password from mysql.user;
+--------+--------------------+-------------------------------------------+
| user   | host               | password                                  |
+--------+--------------------+-------------------------------------------+
| root   | localhost          | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| root   | master |                                           |
| root   | 127.0.0.1          |                                           |
| root   | ::1                |                                           |
|        | localhost          |                                           |
|        | master |                                           |
| rep    | 10.12.237.69       | *9FF2C222F44C7BBA5CC7E3BE8573AA4E1776278C |
| rep    | 10.12.237.69      | *9FF2C222F44C7BBA5CC7E3BE8573AA4E1776278C |
| db1 | 10.12.237.75      | *DEEF4D7D88CD046ECA02A80393B7780A63E7E789 |
| pt | 10.12.237.75      | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
+--------+--------------------+-------------------------------------------+
10 rows in set (0.00 sec)

mysql> drop user 'pt'@'10.12.237.75';
Query OK, 0 rows affected (0.00 sec)

mysql> use pt
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MariaDB [pt]> show tables;
+----------------+
| Tables_in_pt |
+----------------+
| checksums      |
+----------------+
1 row in set (0.00 sec)

MariaDB [pt]> drop table checksums;
Query OK, 0 rows affected (0.00 sec)

MariaDB [pt]> show tables;
Empty set (0.00 sec)
注:主库回收权限。   

五、编写监控脚本,当主从数据不一致时,强制修复数据

背景:在当前的示例中,我们主要监控的是db1库,当主从不一致时强制修复。当然如果需要监控多个数据库,可以编写多个监控脚本。

#思路:计算DIFFS的和值,如果等于0则表示数据一致,如果大于0则表示数据不一致。
[root@master ~]# pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=pt.checksums  --databases=db1 h=10.12.237.75,u=pt,p=123456,P=3306 | awk 'NR>3{sum+=$3}END{print sum}'
0
#扩展计算和值:
sum=0
for i in `cat a.txt`

do
        sum=$(($sum+$i))
done

echo $sum  

监控脚本:
#!/bin/bash

NUM=`/usr/bin/pt-table-checksum --nocheck-replication-filters --no-check-binlog-format --replicate=pt.checksums  --databases=db1 h=10.12.237.75,u=pt,p=123456,P=3306 | awk 'NR>3{sum+=$3}END{print sum}'`

if [ $NUM -eq 0 ];then

    echo "Data is ok!"

else

    echo "Data is error!"
    /usr/bin/pt-table-sync --replicate=pt.checksums h=10.12.237.75,u=pt,p=123456 h=10.12.237.69,u=pt,p=123456 --print
    /usr/bin/pt-table-sync --replicate=pt.checksums h=10.12.237.75,u=pt,p=123456 h=10.12.237.69,u=pt,p=123456 --execute
fi

结合定时任务:crontab -l
#检查主从db1库数据一致性
* * * * * /bin/bash -x /root/mysql-pt.sh > /dev/null 2>&1
* * * * * sleep 10;/bin/bash -x /root/mysql-pt.sh > /dev/null 2>&1
* * * * * sleep 20;/bin/bash -x /root/mysql-pt.sh > /dev/null 2>&1
* * * * * sleep 30;/bin/bash -x /root/mysql-pt.sh > /dev/null 2>&1
* * * * * sleep 40;/bin/bash -x /root/mysql-pt.sh > /dev/null 2>&1
* * * * * sleep 50;/bin/bash -x /root/mysql-pt.sh > /dev/null 2>&1

总结:pt-table-checksum和pt-table-sync工具很给力,工作中常常在使用。注意使用该工具需要授权,一般SELECT, PROCESS, SUPER, REPLICATION SLAVE等权限就已经足够了。

六、pt-heartbeat监控mysql主从复制延迟使用

对于MySQL数据库主从复制延迟的监控,可以借助percona的有力武器pt-heartbeat来实现

pt-heartbeat的工作原理通过使用时间戳方式在主库上更新特定表,然后在从库上读取被更新的时间戳然后与本地系统时间对比来得出其延迟。

具体流程:
1.在主上创建一张heartbeat表,按照一定的时间频率更新该表的字段(把时间更新进去)。监控操作运行后,heartbeat表能促使主从同步!
2.连接到从库上检查复制的时间记录,和从库的当前系统时间进行比较,得出时间的差异。

使用方法(主库和从库上都可以执行监控操作)

pt-hearbeat常用参数
    注意:需要指定的参数至少有 --stop,--update,--monitor,--check。
    其中--update,--monitor和--check是互斥的,--daemonize和--check也是互斥。
    --ask-pass     隐式输入MySQL密码
    --charset      字符集设置
    --check        检查从的延迟,检查一次就退出,除非指定了--recurse会递归的检查所有的从服务器。
    --check-read-only    如果从服务器开启了只读模式,该工具会跳过任何插入。
    --create-table    在主上创建心跳监控的表,如果该表不存在,可以自己手动建立,建议存储引擎改成memory。通过更新该表知道主从延迟的差距。
    heratbeat       表一直在更改ts和position,而ts是我们检查复制延迟的关键。
    --daemonize     执行时,放入到后台执行
    --user=-u,     连接数据库的帐号
    --database=-D, 连接数据库的名称
    --host=-h,     连接的数据库地址
    --password=-p, 连接数据库的密码
    --port=-P,     连接数据库的端口
    --socket=-S,   连接数据库的套接字文件
    --file 【--file=output.txt】   打印--monitor最新的记录到指定的文件,很好的防止满屏幕都是数据的烦恼。
    --frames 【--frames=1m,2m,3m】  在--monitor里输出的[]里的记录段,默认是1m,5m,15m。可以指定1个,如:--frames=1s,多个用逗号隔开。可用单位有秒(s)、分钟(m)、小时(h)、天(d)。
    --interval   检查、更新的间隔时间。默认是见是1s。最小的单位是0.01s,最大精度为小数点后两位,因此0.015将调整至0.02。
    --log        开启daemonized模式的所有日志将会被打印到制定的文件中。
    --monitor    持续监控从的延迟情况。通过--interval指定的间隔时间,打印出从的延迟信息,通过--file则可以把这些信息打印到指定的文件。
    --master-server-id           指定主的server_id,若没有指定则该工具会连到主上查找其server_id。
    --print-master-id    在--monitor和--check 模式下,指定该参数则打印出主的server_id。
    --recurse    多级复制的检查深度。模式M-S-S...不是最后的一个从都需要开启log_slave_updates,这样才能检查到。
    --recursion-method     指定复制检查的方式,默认为processlist,hosts。
    --update    更新主上的心跳表。
    --replace   使用--replace代替--update模式更新心跳表里的时间字段,这样的好处是不用管表里是否有行。
    --stop      停止运行该工具(--daemonize),在/tmp/目录下创建一个“pt-heartbeat-sentinel” 文件。后面想重新开启则需要把该临时文件删除,才能开启(--daemonize)。
    --table     指定心跳表名,默认heartbeat。

实例说明:
master:10.12.237.75
slave:10.12.237.69
同步的库:db1
主从库都能使用pt账号、密码123456登录

先操作针对db1库的检查,其他同步的库的检查操作类似!

1. 主库上的对应库下创建heartbeat表,一般创建后从库会同步这张表(不同步的话,就在从库那边手动也手动创建)
mysql>   CREATE TABLE heartbeat (            
   ts                    varchar(26) NOT NULL,
   server_id             int unsigned NOT NULL PRIMARY KEY,
   file                  varchar(255) DEFAULT NULL,
   position              bigint unsigned DEFAULT NULL,
   relay_master_log_file varchar(255) DEFAULT NULL,
   exec_master_log_pos   bigint unsigned DEFAULT NULL
   );
Query OK, 0 rows affected (0.01 sec)

2.更新主库上的heartbeat,--interval=1表示1秒钟更新一次(注意这个启动操作要在主库服务器上执行)
[root@master ~]# pt-heartbeat  --user=pt --ask-pass --host=10.12.237.75 --create-table --database db1 --interval=1 --update --replace --daemonize
Enter password: 123456
[root@master ~]# ps -ef|grep pt-heartbeat
root     26463     1  0 15:15 ?        00:00:00 perl /usr/bin/pt-heartbeat --user=pt --ask-pass --host=10.12.237.75 --create-table --database db1 --interval=1 --update --replace --daemonize
root     26465 26009  0 15:16 pts/0    00:00:00 grep --color=auto pt-heartbeat

3.在主库运行监测同步延迟(注:必须要带上--master-id)
[root@master ~]# pt-heartbeat --database db1 --table=heartbeat --monitor --host=10.12.237.75 --user=pt --password=123456 --master-server-id=1
0.00s [  0.00s,  0.00s,  0.00s ]
0.00s [  0.00s,  0.00s,  0.00s ]
0.00s [  0.00s,  0.00s,  0.00s ]

...............................................

4. 一次性check出来(--check参数)
[root@master ~]# pt-heartbeat --database db1 --table=heartbeat --check  --host=10.12.237.75 --user=pt --password=123456 --master-server-id=1
0.00

5. 如果想输出自动化监控脚本,则最好记录实时的log日志(--log=/tmp/master-slave.txt)
[root@master ~]#pt-heartbeat --database db1 --table=heartbeat --monitor --host=10.12.237.75 --user=pt --password=123456 --log=/tmp/master-slave.txt --master-server-id=1 --daemonize

注:
1.使用了--check,就不能使用--monit。--update,--monitor和--check是互斥的,--daemonize和--check也是互斥。
2.要测试哪个库,就在哪个库下面创建heartbeat表。
3.如果想把这个输出结果加入自动化监控,那么可以使用如下命令使监控输出写到文件,然后使用脚本定期过滤文件中的最大值作为预警即可:
4.--log选项必须在有--daemonize参数的时候才会打印到文件中,且这个文件的路径最好在/tmp下,否则可能因为权限问题无法创建

监控脚本:
#!/bin/bash

cat /tmp/master-slave.txt > /tmp/master_slave.txt

echo > /tmp/master-slave.txt

sleep 3

max_time=`cat /tmp/master_slave.txt |grep -v '^$' |awk '{print $1}' |sort -k1nr |head -1`
#不显示开头是$的内容,打印出出第一列,第一列按字符串数值降序,最后一行
NUM=$(echo "$max_time"|cut -d"s" -f1)

if [[ "$NUM" == "0.00" ]];then

    echo "Mysql主从数据一致"

else

    echo "Mysql主从数据不一致"

fi

结合crontab,每隔一分钟检查一次
crontab -e
#mysql主从同步延迟检查
* * * * * /bin/bash -x /root/mysql-heartbeat.sh > /dev/null 2>&1


如何关闭上面在主库上执行的heartbeat更新进程呢?
方法一:可以用参数--stop去关闭
[root@master ~]# ps -ef|grep heartbeat
root        762      1  0 17:11 ?        00:00:00 perl /usr/bin/pt-heartbeat --user=pt --ask-pass --host=10.12.237.75 --create-table --database db1 --interval=1 --interval=1 --update --replace --daemonize
root       1591 101010  0 17:14 pts/1    00:00:00 grep --color=auto heartbeat
root     128419      1  0 17:03 ?        00:00:00 perl /usr/bin/pt-heartbeat --database db1 --table=heartbeat --monitor --host=10.12.237.75 --user=pt --password=123456 --log=/tmp/master-slave.txt --master-server-id=1 --daemonize

[root@master ~]# pt-heartbeat --stop
Successfully created file /tmp/pt-heartbeat-sentinel
[root@master ~]# ps -ef|grep heartbeat
root       1769 101010  0 17:14 pts/1    00:00:00 grep --color=auto heartbeat
这样就把在主上开启的进程杀掉了。
但是后续要继续开启后台进行的话,记住一定要先把/tmp/pt-heartbeat-sentinel 文件删除,否则启动不了

方法二:直接kill掉进程pid(推荐这种方法)

综合测试结果
[root@master ~]# ./mysql-pt.sh 
Data is ok!
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# ./mysql-heartbeat.sh 
Mysql主从数据一致
[root@master ~]# 


七、注意事项:

pt-table-checksum:

如果表没有主键或唯一索引,或者干脆没有任何索引,那么pt工具在chunk表的时候,将无所适从。不过我们已强制在建表的时候,每个表都必须有主键。 –check-binlog-format是默认选项,建议不要关闭它。pt-table-checksum工具自身产生的所有sql语句要基于语句格式 同步到从库,这是由它的实现原理决定的。但是在A-B-C的级联复制结构中,如果B是行格式的复制,那么B与C的数据一致性校验就没法做了。在A上设置该 sql语句为语句级并不会把set这个动作记录到binlog中,这个属性无法级联传递。 主从异构的情况下,checksum语句可能在从库上执行失败,即使是索引的不一致。例如sql语句中有force index某个索引,但是从库的表上没有这个索引,就会导致卡库。

pt-table-sync:

采用replace into来修复主从不一致,必须保证被replace的表上有主键或唯一键,否则replace into退化成insert into,起不到修复的效果。这种情况下pt-table-sync会采用其他校验和修复算法,但是效率非常低,例如对所有列的group by然后求count(*)(表一定要有主键!)。 主从数据不一致需要通过replace into来修复,该sql语句必须是语句级。pt-table-sync会把它发起的所有sql语句都设置为statement格式,而不管全局的 binlog_format值。这在级联A-B-C结构中,也会遇到pt-table-checksum曾经遇到的问题,引起行格式的中继库的从库卡库是 必然。不过pt-table-sync默认会无限递归的对从库的binlog格式进行检查并警告: 由于pt-table-sync每次只能修复一个表,所以如果修复的是父表,则可能导致子表数据连带被修复,这可能会修复一个不一致而引入另一个不一致; 如果表上有触发器,也可能遇到同样问题。所以在有触发器和主外键约束的情况下要慎用。pt-table-sync工具同样也不欢迎主从异构的结构。pt- table-sync工具默认会进行先决条件的检查。 pt-table-sync在修复过程中不能容忍从库延迟,这正好与pt-table-checksum相反。如果从库延迟太多,pt-table- sync会长期持有对chunk的for update锁,然后等待从库的master_pos_wait执行完毕或超时。从库延迟越大,等待过程就越长,主库加锁的时间就越长,对线上影响就越 大。因此要严格设置max-lag。 对从库数据的修复通常是在主库执行sql来同步到从库。因此,在有多个从库时,修复某个从库的数据实际会把修复语句同步到所有从库。数据修复的代价取决于 从库与主库不一致的程度,如果某从库数据与主库非常不一致,举例说,这个从库只有表结构,那么需要把主库的所有数据重新灌一遍,然后通过binlog同 步,同时会传递到所有从库。这会给线上带来很大压力,甚至拖垮集群。正确的做法是,先用pt-table-checksum校验一遍,确定不一致的程度: 如果不同步的很少,用pt-table-sync直接修复;否则,用备份先替换它,然后用pt-table-sync修复。 说明: 这实际提供了一种对myisam备份的思路:如果仅有一个myisam的主库,要为其增加从库,则可以:先mysqldump出表结构到从库上,然后启动 同步,然后用pt-table-sync来修复数据。

你可能感兴趣的:(shujuku)