背景
mysql设置了主从同步,通过show slave status查看,Slave_IO_Running和Slave_SQL_Running都是yes,但实际发现有几张表没有同步成功。
原因
Slave_IO_Running: Yes 和 Slave_SQL_Running: Yes 只能证明通信管道是正常的,即:
IO线程能正常从主库拉取 Binlog。
SQL线程正在正常执行 Binlog 中的语句,没有因为报错而停止。
但这并不代表主从数据是一致的。出现这种“状态正常但数据不一致”的情况。
如何检查
使用专业工具 Percona Toolkit 中的 pt-table-checksum。
它会在 Slave 上计算校验值,你可以看到哪些具体的表 DIFF 不为 0。
安装依赖
CentOS / RHEL / AlmaLinux / Rocky Linux:
# 安装基础 Perl DBI 模块
sudo yum install -y perl-DBI
# 安装 MySQL 驱动模块 (必须安装,否则会报 DBD::mysql 缺失)
sudo yum install -y perl-DBD-MySQL
# 如果报错提示缺少 Time::HiRes
sudo yum install -y perl-Time-HiRes
Ubuntu / Debian:
# 更新索引
sudo apt-get update
# 安装基础 Perl DBI 和 MySQL 驱动模块
sudo apt-get install -y libdbi-perl libdbd-mysql-perl
# 如果报错提示缺少 Time::HiRes
sudo apt-get install -y libtime-hires-perl
验证依赖是否安装成功
执行以下两条命令,如果没有报错,说明安装成功:
perl -MDBI -e 'print "DBI OK\n"'
perl -MDBD::mysql -e 'print "MySQL Driver OK\n"'
安装 Percona Toolkit
# 下载最新版本
wget https://downloads.percona.com/downloads/percona-toolkit/3.5.5/binary/tarball/percona-toolkit-3.5.5_x86_64.tar.gz
# 解压
tar -xzf percona-toolkit-3.5.5_x86_64.tar.gz
# 移动到系统路径
sudo cp percona-toolkit-3.5.5/bin/* /usr/local/bin/
# 验证
pt-table-checksum --version
创建检测用的数据库用户(在主库执行)
-- 创建专用用户
CREATE USER 'checksum'@'%' IDENTIFIED BY 'your_password';
-- 授权(需要较高权限)
GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE ON *.* TO 'checksum'@'%';
GRANT ALL PRIVILEGES ON percona.* TO 'checksum'@'%';
-- 刷新权限
FLUSH PRIVILEGES;
注意: 该用户需要在主库和从库都能登录,且权限一致。
开始检测
pt-table-checksum \
--host=[数据库地址] \
--user=[数据库账号] \
--password=[数据库密码] \
--replicate=percona.checksums \
--recursion-method hosts \
--no-check-binlog-format
--databases=[数据库名] # 明确指定数据库,去掉这行则检查所有的数据库
结果解读
输出示例
TS ERRORS DIFFS ROWS DIFF_ROWS CHUNKS SKIPPED TIME TABLE
12-20T10:30:15 0 0 15000 0 3 0 1.234 your_db.table1
12-20T10:30:18 0 1 23000 150 5 0 2.456 your_db.table2
12-20T10:30:20 0 0 5000 0 1 0 0.789 your_db.table3
字段含义:
- TS: 检测时间戳
- ERRORS: 执行错误数(如权限不足)
- DIFFS: 不一致的 chunk 数量(关键指标)
- ROWS: 总行数
- DIFF_ROWS: 不一致的行数(关键指标)
- CHUNKS: 分块数
- SKIPPED: 跳过的块数
- TABLE: 表名
如果 DIFFS > 0,说明该表主从数据不一致!
查看详细的不一致记录
-- 在主库查询检测结果表
USE percona;
-- 查看所有不一致的表
SELECT db, tbl, SUM(this_cnt) AS master_cnt, SUM(master_cnt) AS slave_cnt
FROM checksums
WHERE master_cnt <> this_cnt OR master_crc <> this_crc
GROUP BY db, tbl;
-- 查看具体哪个从库不一致
SELECT *
FROM checksums
WHERE master_cnt <> this_cnt OR master_crc <> this_crc;