下文主要给大家带来如何使用percona-toolkit工具检查及修复MySQL数据库的主从不一致,希望这些内容能够带给大家实际用处,这也是我如何使用percona-toolkit工具检查及修复MySQL数据库的主从不一致编辑这篇文章的主要目的。好了,废话不多说,大家直接看下文吧。
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会暂停直到赶上主库的计算时间点(也通过选项--设定一个可容忍的延迟最大值,超过这个值也认为不一致)。
select * from percona.checksums where master_cnt <> this_cnt OR master_crc <> this_crc OR ISNULL(master_crc) <> ISNULL(this_crc) \G
IP | Port | 主机名 | 作用 |
---|---|---|---|
192.168.1.101 | 3306 | node1 | master |
192.168.1.102 | 3306 | node2 | slave |
打开官网:https://www.percona.com/downloads/percona-toolkit/LATEST/
选择软件版本:Version,一般默认最新版即可;
选择系统版本:Software,也可以源码编译;我的CentOS6
系统架构:Hardware;我的64位;
我的下载为:
https://www.percona.com/downloads/percona-toolkit/3.0.13/binary/redhat/6/x86_64/percona-toolkit-debuginfo-3.0.13-1.el6.x86_64.rpm
https://www.percona.com/downloads/percona-toolkit/3.0.13/binary/redhat/6/x86_64/percona-toolkit-3.0.13-1.el6.x86_64.rpm
yum install percona-toolkit-3.0.13-1.el6.x86_64.rpm -y yum install percona-toolkit-debuginfo-3.0.13-1.el6.x86_64.rpm -y
CentOS6.*依赖:
perl-DBD-MySQL perl-DBI perl-IO-Socket-SSL perl-Net-LibIDN perl-Net-SSLeay perl-Time-HiRes
perl-Compress-Raw-Bzip2 perl-Compress-Raw-Zlib perl-DBD-MySQL perl-DBI perl-Digest perl-Digest-MD5 perl-IO-Compress perl-IO-Socket-IP perl-IO-Socket-SSL perl-Mozilla-CA perl-Net-Daemon perl-Net-LibIDN perl-Net-SSLeay perl-PlRPC
查看安装的文件:
[root@node1 ~]# rpm -ql percona-toolkit /usr/bin/pt-align /usr/bin/pt-archiver /usr/bin/pt-config-diff /usr/bin/pt-deadlock-logger /usr/bin/pt-diskstats /usr/bin/pt-duplicate-key-checker /usr/bin/pt-fifo-split /usr/bin/pt-find /usr/bin/pt-fingerprint /usr/bin/pt-fk-error-logger /usr/bin/pt-heartbeat /usr/bin/pt-index-usage /usr/bin/pt-ioprofile /usr/bin/pt-kill /usr/bin/pt-mext /usr/bin/pt-mongodb-query-digest /usr/bin/pt-mongodb-summary /usr/bin/pt-mysql-summary /usr/bin/pt-online-schema-change /usr/bin/pt-pmp /usr/bin/pt-query-digest /usr/bin/pt-secure-collect /usr/bin/pt-show-grants /usr/bin/pt-sift /usr/bin/pt-slave-delay /usr/bin/pt-slave-find /usr/bin/pt-slave-restart /usr/bin/pt-stalk /usr/bin/pt-summary /usr/bin/pt-table-checksum # 校验数据一致性; /usr/bin/pt-table-sync # 修复不一致数据; /usr/bin/pt-table-usage /usr/bin/pt-upgrade /usr/bin/pt-variable-advisor /usr/bin/pt-visual-explain ... ... [root@node1 ~]#
root@node1 10:56: [(none)]> create database pt_check; Query OK, 1 row affected (0.04 sec) root@node1 10:57: [(none)]> use pt_check Database changed root@node1 10:58: [pt_check]> create table test1(id int auto_increment primary key,name varchar(20) not null); Query OK, 0 rows affected (0.86 sec) root@node1 11:03: [pt_check]> insert into test1 values(null,'will'); Query OK, 1 row affected (0.00 sec) root@node1 11:03: [pt_check]> insert into test1 values(null,'jim'); Query OK, 1 row affected (0.00 sec) root@node1 11:03: [pt_check]> insert into test1 values(null,'tom'); Query OK, 1 row affected (0.05 sec) root@node1 11:03: [pt_check]> select * from pt_check.test1; +----+------+ | id | name | +----+------+ | 1 | will | | 2 | jim | | 3 | tom | +----+------+ 3 rows in set (0.00 sec) root@node1 11:04: [pt_check]>
root@node1 11:03: [pt_check]> select * from pt_check.test1; +----+------+ | id | name | +----+------+ | 1 | will | | 2 | jim | | 3 | tom | +----+------+ 3 rows in set (0.00 sec) root@node1 11:04: [pt_check]> delete from pt_check.test1 where id='2'; Query OK, 1 row affected (0.02 sec) root@node2 12:23: [(none)]> select * from pt_check.test1; +----+------+ | id | name | +----+------+ | 1 | will | | 3 | tom | +----+------+ 2 rows in set (0.00 sec) root@node2 12:23: [(none)]>
root@node1 12:28: [pt_check]> GRANT CREATE,INSERT,SELECT,DELETE,UPDATE,LOCK TABLES,PROCESS,SUPER,REPLICATION SLAVE ON *.* TO 'ptuser'@'192.168.1.101' IDENTIFIED BY '123456'; Query OK, 0 rows affected (0.00 sec) root@node1 12:29: [pt_check]> flush privileges; Query OK, 0 rows affected (0.00 sec) root@node1 12:29: [pt_check]> select Host,User from mysql.user; +----------------+---------------+ | Host | User | +----------------+---------------+ | localhost | root | | localhost | mysql.session | | localhost | mysql.sys | | 172.16.156.% | rep | | % | java | | 192.168.1.101 | ptuser | +----------------+---------------+ 9 rows in set (0.00 sec) root@node1 12:29: [pt_check]>
root@node2 12:48: [(none)]> select Host,User from mysql.user; +----------------+---------------+ | Host | User | +----------------+---------------+ | localhost | root | | localhost | mysql.session | | localhost | mysql.sys | | 172.16.156.% | rep | | % | java | | 192.168.1.101 | ptuser | +----------------+---------------+ 8 rows in set (0.00 sec) root@node2 12:48: [(none)]>
--recursion-method:发现从库的方式。pt-table-checksum 默认可以在主库的 processlist 中找到从库复制进程,从而识别出有哪些从库,但如果使用是非标准3306端口,会导致找不到从库信息。此时就会自动采用host方式,但需要提前在从库 my.cnf 里面配置report_host、report_port信息,如:
report_host = MASTER_HOST report_port = 13306
最终极的办法是dsn,dsn指定的是某个表(如 percona.dsns ),表行记录是改主库的(多个)从库的连接信息。适用以下任一情形:
我比较倾向使用DSN的方式。这个dsns表只需要在执行 pt-table-checksum 命令的云服务器上能够访问到就行。这里纠正一个认识,网上很多人说 pt-table-checksum 要在主库上执行,其实不是的,我的mysql实例比较多,只需在某一台云服务器上安装percona-toolkit,这台服务能够同时访问主库和从库就行了。具体用法见后面实例。
[root@node1 ~]# pt-table-checksum --nocheck-replication-filters --replicate=test.checksums --databases=pt_check --tables=test1 h=192.168.1.101,u=ptuser,p=123456,P=3306 Checking if all tables can be checksummed ... Starting checksum ... Replica node2 has binlog_format ROW 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. [root@node1 ~]#
从库node2的bbinlog日志为ROW,这可能导致pt-table-checksum中断复制。可以指定--no-check-binlog-format以禁用此检查。
[root@node1 ~]# pt-table-checksum --nocheck-replication-filters --replicate=test.checksums --databases=pt_check --tables=test1 h=192.168.1.101,u=ptuser,p=123456,P=3306 --no-check-binlog-format Checking if all tables can be checksummed ... Starting checksum ... TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE 02-19T18:23:22 0 1 3 0 1 0 0.045 pt_check.test1 [root@node1 ~]#
看到已经检查出主从数据有不一致了,DIFFS下的值为1,怎么不一致呢? 通过指定--replicate=test.checksums 参数,就说明把检查信息都写到了checksums表中
root@node1 09:19: [(none)]> select * from test.checksums \G *************************** 1. row *************************** db: pt_check tbl: test1 chunk: 1 chunk_time: 0.005212 chunk_index: NULL lower_boundary: NULL upper_boundary: NULL this_crc: b9a54161 this_cnt: 3 # 本机 3行数据 master_crc: b9a54161 master_cnt: 3 # master 3行数据 ts: 2019-02-20 09:18:01 1 row in set (0.00 sec) root@node1 09:19: [(none)]>
root@node2 09:20: [(none)]> select * from test.checksums \G *************************** 1. row *************************** db: pt_check tbl: test1 chunk: 1 chunk_time: 0.005212 chunk_index: NULL lower_boundary: NULL upper_boundary: NULL this_crc: d49ddeb7 this_cnt: 2 # 本机 2行数据 master_crc: b9a54161 master_cnt: 3 # master 3行数据 ts: 2019-02-20 09:18:01 1 row in set (0.01 sec) root@node2 09:20: [(none)]>
master库用pt-table-sync命令和--print选项打印出master下的check_sum.test1和slave库的check_sum.test1的不一致的数据,如下:
[root@node1 ~]# pt-table-sync --replicate=test.checksums h=192.168.1.101,u=ptuser,p=123456,P=3306 h=192.168.1.102,u=ptuser,p=123456,P=3306 --print REPLACE INTO `pt_check`.`test1`(`id`, `name`) VALUES ('2', 'jim') /*percona-toolkit src_db:pt_check src_tbl:test1 src_dsn:P=3306,h=192.168.1.101,p=...,u=ptuser dst_db:pt_check dst_tbl:test1dst_dsn:P=3306,h=node2,p=...,u=ptuser lock:1 transaction:1 changing_src:test.checksums replicate:test.checksums bidirectional:0 pid:20377 user:root host:node1*/; [root@node1 ~]#
--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@node1 ~]# pt-table-sync --replicate=test.checksums h=192.168.1.101,u=ptuser,p=123456,P=3306 h=192.168.1.102,u=ptuser,p=123456,P=3306 --execute
[root@node1 ~]# pt-table-checksum --nocheck-replication-filters --replicate=test.checksums --databases=pt_check --tables=test1 h=192.168.1.101,u=ptuser,p=123456,P=3306 --no-check-binlog-format Checking if all tables can be checksummed ... Starting checksum ... TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE 02-20T10:03:02 0 0 3 0 1 0 0.083 pt_check.test1 [root@node1 ~]#
可以看到再次检查的时候,DIFFS已经是0了;
root@node1 10:05: [(none)]> select * from pt_check.test1; +----+------+ | id | name | +----+------+ | 1 | will | | 2 | jim | | 3 | tom | +----+------+ 3 rows in set (0.00 sec) root@node1 10:05: [(none)]>
root@node2 10:02: [(none)]> select * from pt_check.test1; +----+------+ | id | name | +----+------+ | 1 | will | | 2 | jim | | 3 | tom | +----+------+ 3 rows in set (0.00 sec) root@node2 10:05: [(none)]>
已经跟master上的数据一致了。
没有创建CREATE表的权限;
[root@node1 ~]# pt-table-checksum --nocheck-replication-filters --replicate=test.checksums --databases=pt_check --tables=test1 h=192.168.1.101,u=ptuser,p=123456,P=3306 --no-check-binlog-format Checking if all tables can be checksummed ... Starting checksum ... 02-19T18:08:22 --create-replicate-table failed: DBD::mysql::db do failed: CREATE command denied to user 'ptuser'@'node1' for table 'checksums' [for Statement " CREATE TABLE IF NOT EXISTS `test`.`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 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (db, tbl, chunk), INDEX ts_db_tbl (ts, db, tbl) ) ENGINE=InnoDB DEFAULT CHARSET=utf8"] at /usr/bin/pt-table-checksum line 12272. 02-19T18:08:22 --replicate table checksums does not exist and it cannot be created automatically. You need to create the table. [root@node1 ~]#
不能自动找到从库,确认processlist或host或dsns方式用对了。
可以在pt-table-checksum命令前加PTDEBUG=1来看详细的执行过程,如端口、用户名、权限错误。
问题出在 percona.checksums 表在从库不存在,根本原因是没有从主库同步过来,所以看一下从库是否延迟严重。
反复打印出类似上面停止检查的信息。这是因为当前数据库正在运行的线程数大于默认25,pt-table-checksum 为了减少对库的压力暂停检查了。等数据库压力过了就好了,或者也可以直接 Ctrl+C 终端,下一次加上--resume继续执行,或者加大--max-load=值。
对于以上关于如何使用percona-toolkit工具检查及修复MySQL数据库的主从不一致,大家是不是觉得非常有帮助。如果需要了解更多内容,请继续关注我们的行业资讯,相信你会喜欢上这些内容的。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。