简介
这次主要包含两个工具,都可以在percona-tookit里面找到
pt-table-checksum
pt-table-sync
pt-table-checksum
#简介
pt-table-checksum主要可以用来校验主从数据的一致性,一主多从,一主单从都可以
#常用参数
--no-check-replication-filters 不检查复制过滤
--no-check-binlog-format 不检查binlog格式,因为binlog这里需要使用statement格式
--replicate 检查的结果写到,哪个db的checksums表中
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 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (db, tbl, chunk),
INDEX ts_db_tbl (ts, db, tbl)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--chunk-size 默认1000条记录一个chunk去做query
--ignore-columns 指定需要忽略校验的字段,如有多个则用','(逗号)隔开。
--ignore-databases 指定需要忽略校验的数据库,如有多个则用','(逗号)隔开。
--ignore-databases-regex 指定采用正则表达式匹配忽略校验的数据库。
--ignore-engines 默认值:FEDERATED,MRG_MyISAM指定需要忽略校验的存储引擎类型的表,如有多个则用','(逗号)隔开。
--ignore-tables 忽略检查哪个表
--ignore-tables-regex 忽略检查哪个表,政策表达式
--max-lag 主从延迟达到多少就停止,默认1s
--max-load 可以指定负载,默认threads-running=25
--progress 进度
--tables check表
--tables-regex=user_watch_tab* 只check哪个表,正则表达式
--ask-pass 需要显示输入密文
--replicate-check-only 只校验结果不一致的数据库
--recursion-method 默认值:processlist,hosts
指定获取从库的方式。pt-table-checksum在执行校验操作时会执行多次REPLICA CHECKS操作。
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
==========================================================
processlist:通过SHOW PROCESSLIST方式找到slave,为默认方式,当SHOW SLAVE HOSTS不可用时。一旦实例运行在非3306端口上时,hosts方式就会变为默认方式;
hosts:通过SHOW SLAVE HOSTS方式找到slave,hosts方式要求从库配置'--report_host'和'--report_port'这两个参数;
cluster:基于集群版本Galera 23.7.3及更新版本;
dsn:通过读取表中从库的DSN信息进行连接。
dsn是表,对于多个slave的时候,dsn表最好
CREATE TABLE `dsns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`dsn` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
#检查不一致的sql
SELECT db, tbl, SUM(this_cnt) AS total_rows, COUNT(*) AS chunks
FROM percona.checksums
WHERE (
master_cnt <> this_cnt
OR master_crc <> this_crc
OR ISNULL(master_crc) <> ISNULL(this_crc))
GROUP BY db, tbl;
pt-table-sync
#简介
用于修复主从不一致的数据
#常用参数
--replicate= :指定通过pt-table-checksum得到的表,这2个工具差不多都会一直用。
--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 :执行命令。
--transaction 指定工具操作使用事务代替LOCK TABLES语句进行锁表。
--verbose. 打印出更详细的信息
--recursion-method 获得从库的信息,默认值:processlist,hosts 还有另外一个none
#常用用法
1.Resolve differences that pt-table-checksum found on all slaves of master1:
pt-table-sync --execute --replicate test.checksum master1
2.Same as above but only resolve differences on slave1
pt-table-sync --execute --replicate test.checksum \
--sync-to-master slave1
#注意点
如果使用了非3306端口,会使用show slave hosts去获得ip,查找slave。
如果拿掉外网IP这些会导致找不到slave,不能一次性操作多个
需要一个一个以上面第二种方式操作。
实际操作
#实际用法
#1.先在master上创建用户,可以连接到所有slave,并授权
create user 'pt-table-check'@'master_ip' identified by '$pass';
grant SELECT, PROCESS, SUPER, REPLICATION SLAVE,lock tables on *.* to 'pt-table-check'@'master_ip';
grant CREATE, INSERT, UPDATE, DELETE on test.* to 'pt-table-check'@'master_ip';
#2.master创建dsn slave table表,并插入数据
CREATE TABLE `test`.`dsns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`dsn` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
insert into test.dsns(dsn) values ("h=s1ip,P=6606,u=pt-table-check,p=");
insert into test.dsns(dsn) values ("h=s2ip,P=6606,u=pt-table-check,p=");
insert into test.dsns(dsn) values ("h=s3ip,P=6606,u=pt-table-check,p=");
insert into test.dsns(dsn) values ("h=s4ip,P=6606,u=pt-table-check,p=");
insert into test.dsns(dsn) values ("h=s5ip,P=6606,u=pt-table-check,p=");
insert into test.dsns(dsn) values ("h=s6ip,P=6606,u=pt-table-check,p=");
#3.开始进行check,这里进行正则匹配
pt-table-checksum h=master_ip,P=6606,u='pt-table-check' --no-check-replication-filters --no-check-binlog-format --ask-pass --max-lag=1 --max-load='Threads_running=25' --replicate=test.checksums --databases=jiawei_test --tables-regex=user_watch_tab* --recursion-method dsn=h=dsn表的ip,u='pt-table-check',p='$pass',P=6606,D=test,t=dsns
Checksumming jiawei_test.user_watch_tab_00000041: 22% 01:42 remain
Checksumming jiawei_test.user_watch_tab_00000041: 42% 01:22 remain
Checksumming jiawei_test.user_watch_tab_00000041: 62% 00:54 remain
Checksumming jiawei_test.user_watch_tab_00000041: 85% 00:20 remain
06-16T19:52:32 0 1 50933486 0 207 0 173.857 jiawei_test.user_watch_tab_00000041
#4.slave查询结果表,查看不一致的
SELECT db, tbl, SUM(this_cnt) AS total_rows, COUNT(*) AS chunks
FROM percona.checksums
WHERE (
master_cnt <> this_cnt
OR master_crc <> this_crc
OR ISNULL(master_crc) <> ISNULL(this_crc))
GROUP BY db, tbl;
>SELECT db, tbl, SUM(this_cnt) AS total_rows, COUNT(*) AS chunks
-> FROM test.checksums
-> WHERE (
-> master_cnt <> this_cnt
-> OR master_crc <> this_crc
-> OR ISNULL(master_crc) <> ISNULL(this_crc))
-> GROUP BY db, tbl;
+------------------+-------------------------+------------+--------+
| db | tbl | total_rows | chunks |
+------------------+-------------------------+------------+--------+
| jiawei_test | user_watch_tab_00000000 | 258163 | 1 |
| jiawei_test | user_watch_tab_00000003 | 244324 | 1 |
| jiawei_test | user_watch_tab_00000004 | 252323 | 1 |
| jiawei_test | user_watch_tab_00000006 | 246460 | 1 |
| jiawei_test | user_watch_tab_00000011 | 248913 | 1 |
| jiawei_test | user_watch_tab_00000016 | 248169 | 1 |
| jiawei_test | user_watch_tab_00000020 | 247681 | 1 |
| jiawei_test | user_watch_tab_00000021 | 241514 | 1 |
| jiawei_test | user_watch_tab_00000022 | 247455 | 1 |
| jiawei_test | user_watch_tab_00000025 | 249253 | 1 |
| jiawei_test | user_watch_tab_00000028 | 255769 | 1 |
| jiawei_test | user_watch_tab_00000034 | 247704 | 1 |
| jiawei_test | user_watch_tab_00000041 | 249859 | 1 |
| jiawei_test | user_watch_tab_00000053 | 251265 | 1 |
| jiawei_test | user_watch_tab_00000056 | 245363 | 1 |
| jiawei_test | user_watch_tab_00000065 | 245756 | 1 |
| jiawei_test | user_watch_tab_00000072 | 246405 | 1 |
| jiawei_test | user_watch_tab_00000077 | 249218 | 1 |
| jiawei_test | user_watch_tab_00000084 | 253561 | 1 |
| jiawei_test | user_watch_tab_00000091 | 249323 | 1 |
| jiawei_test | user_watch_tab_00000098 | 248128 | 1 |
+------------------+-------------------------+------------+--------+
21 rows in set (0.02 sec)
#5.是用pt-table-sync可以先打印出来数据,简单check下
#如果是3306端口,且可以通过show slave hosts找到地址
pt-table-sync --print --replicate test.checksum h=masterip,P=6606,u='pt-table-check' --transaction --verbose --ask-pass
#如果上述不满足
pt-table-sync --print --replicate test.checksums --sync-to-master h=s1ip,P=6606,u='pt-table-check' --ask-pass --transaction --verbose
可以手动执行,注意sql-log-bin=0,不要写binlog
也可以直接--execute自动执行
#master执行
# pt-table-sync --print --replicate test.checksums --sync-to-master h=s1ip,P=6606,u='pt-table-check' --ask-pass --transaction --verbose 2>&1 >> /data/scripts/repair.sql
Enter password for s1ip:
# Syncing via replication P=6606,h=s1ip,p=...,u=pt-table-check
# DELETE REPLACE INSERT UPDATE ALGORITHM START END EXIT DATABASE.TABLE
REPLACE INTO `jiawei_test`.`user_watch_tab_00000000`(column_names) VALUES (values) /*percona-toolkit src_db:jiawei_test src_tbl:user_watch_tab_00000000 src_dsn:P=6606,h=master_ip,p=...,u=pt-table-check dst_db:jiawei_test dst_tbl:user_watch_tab_00000000 dst_dsn:P=6606,h=s1ip,p=...,u=pt-table-check lock:1 transaction:1 changing_src:test.checksums replicate:test.checksums bidirectional:0 pid:9758 user:root hostname*/;
#获取执行结果然后执行
mysql -u -p -e "set sql_log_bin=0;source /data/scripts/repair.sql;"
#6.check一下数据是否一样了
主从分别查询修复的数据是否一致。
至此数据修复完毕。
#备注
分析的时候会对对应的块加锁。
操作的时候会有压力?
可以看到我在线上操作的时候数据库基本没有任何压力。该工具并不会对数据库产生任何性能影响。