mysql-主从数据一致性检查工具 pt-table-checksum

发布时间 2023-06-14 17:21:00作者: 白露~

pt-table-checksum 工具介绍

pt-table-checksum 是 Percona Toolkit 的一个组件,用于检测 MySQL 主、从库的数据是否一致。它的原理是在主库执行基于 statement 的 SQL 语句来生成主库数据块的 checksum,把相同的 SQL 语句传递到从库执行,并在从库上计算相同数据块的 checksum,最后,比较主从库上相同数据块的 checksum 值,由此判断主从数据是否一致12。

为什么要使用 pt-table-checksum

MySQL 复制是一种让你可以轻松地维护 MySQL 数据的多个副本的过程,通过将它们从主库自动复制到从库。保证从库有与主库相同的数据集是非常重要的,以确保复制流中的数据一致性。MySQL 从库数据可能因为许多原因而与主库不一致,例如复制错误、在从库上意外地直接更新等。Percona 的支持工程师强烈建议客户定期运行 pt-table-checksum 工具来验证复制流中的数据一致性。特别是在修复从库上的复制错误后,要确保从库与主库有相同的数据。你不想让自己处于这样一种情况:出于某种原因,你需要切换到一个从库,然后你发现在那个从库上有不同的数据3。

如何使用 pt-table-checksum

pt-table-checksum 是一个命令行工具,可以在任何 MySQL 服务器上运行,通常是在主服务器上运行。它有许多选项可以控制它的行为和输出。下面是一些常用的选项:

  • --databases:指定要校验的数据库名称,可以用逗号分隔多个数据库。
  • --tables:指定要校验的表名称,可以用逗号分隔多个表。
  • --ignore-databases:指定要忽略的数据库名称,可以用逗号分隔多个数据库。
  • --ignore-tables:指定要忽略的表名称,可以用逗号分隔多个表。
  • --recursion-method:指定如何发现从库,默认是通过主库的进程列表。如果这种方法失败,可以尝试其他方法,如 hostscluster 或 dsn
  • --replicate:指定存储校验和结果的表名,默认是 percona.checksums
  • --nocheck-replication-filters:指定是否忽略复制过滤器,默认是不忽略。复制过滤器可能会导致复制失败或数据不一致。
  • --nocheck-binlog-format:指定是否忽略二进制日志格式,默认是不忽略。如果二进制日志格式是 ROW,可能会导致 pt-table-checksum 中断复制。
  • --max-load:指定在服务器上执行校验和之前检查的最大负载值,默认是 Threads_running=25。如果负载过高,则 pt-table-checksum 会暂停。
  • --max-lag:指定允许从库落后主库的最大秒数,默认是 1 秒。如果落后过多,则 pt-table-checksum 会暂停。

更多选项可以参考 pt-table-checksum 文档。

pt-table-checksum 的使用示例

单主单从复制

在这个示例中,我们有一个简单的单主单从复制拓扑,主库的地址是 192.168.88.82,从库的地址是 192.168.88.83。我们在主库上创建了一个测试数据库和一个测试表,并插入了一些数据。然后我们在从库上故意修改了一些数据,造成数据不一致。

# 在主库上创建测试数据库和表,并插入数据
mysql -h 192.168.88.82 -u root -p
mysql> create database test;
mysql> use test;
mysql> create table t1 (id int primary key, name varchar(10));
mysql> insert into t1 values (1, 'Alice'), (2, 'Bob'), (3, 'Charlie'), (4, 'David');
mysql> select * from t1;
+----+---------+
| id | name    |
+----+---------+
|  1 | Alice   |
|  2 | Bob     |
|  3 | Charlie |
|  4 | David   |
+----+---------+
4 rows in set (0.00 sec)

# 在从库上修改数据,造成不一致
mysql -h 192.168.88.83 -u root -p
mysql> use test;
mysql> update t1 set name = 'Eve' where id = 2;
mysql> select * from t1;
+----+---------+
| id | name    |
+----+---------+
|  1 | Alice   |
|  2 | Eve     |
|  3 | Charlie |
|  4 | David   |
+----+---------+
4 rows in set (0.00 sec)

接下来,我们在主库上运行 pt-table-checksum 工具,指定要校验的数据库和表,以及从库的地址和端口。

# 在主库上运行 pt-table-checksum
pt-table-checksum -h 192.168.88.82 -u root -p --databases test --tables t1 --recursion-method hosts

运行 pt-table-checksum 后,我们可以看到以下输出:

# pt-table-checksum output
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
10-12T10:36:33      0      1        4       1       0   0.014 test.t1

这个输出告诉我们,pt-table-checksum 发现了一个数据不一致的情况,就是在 test.t1 表中。它还显示了校验的时间、行数、块数等信息。我们可以在从库上查看 percona.checksums 表,它存储了校验和的结果。我们可以看到主从库上的 checksum 值不同,这就是数据不一致的原因。

# 在主库上查看 percona.checksums 表
mysql -h 192.168.88.82 -u root -p
mysql> select db, tbl, chunk, this_cnt, this_crc from percona.checksums where db = 'test' and tbl = 't1';
+------+-----+-------+----------+------------+
| db   | tbl | chunk | this_cnt | this_crc   |
+------+-----+-------+----------+------------+
| test | t1  |     1 |        4 | 3950759929 |
+------+-----+-------+----------+------------+
1 row in set (0.00 sec)

# 在从库上查看 percona.checksums 表
mysql -h 192.168.88.83 -u root -p
mysql> select db, tbl, chunk, this_cnt, this_crc from percona.checksums where db = 'test' and tbl = 't1';
+------+-----+-------+----------+------------+
| db   | tbl | chunk | this_cnt | this_crc   |
+------+-----+-------+----------+------------+
| test | t1  |     1 |        4 | **4190678858** |
+------+-----+-------+----------+------------+
1 row in set (0.00 sec)
注意,从库上的 this_crc 值是 4190678858,而主库上的是 3950759929。这就说明了从库上的数据有变化,导致了校验和不匹配。为了修复这个问题,我们可以使用另一个 Percona Toolkit 的组件,叫做 pt-table-sync。这个工具可以同步主从库上的数据,使它们保持一致。我们将在下一节介绍如何使用 pt-table-sync 工具.
 

如何使用 pt-table-sync

pt-table-sync 是一个命令行工具,可以同步主从库上的数据,使它们保持一致。它有两种模式:检查模式和执行模式。检查模式只是显示需要执行的 SQL 语句,但不实际执行。执行模式则会真正地执行 SQL 语句,来修复数据不一致的问题。我们可以使用 --dry-run 选项来切换模式。下面是一些常用的选项:

  • --databases:指定要同步的数据库名称,可以用逗号分隔多个数据库。
  • --tables:指定要同步的表名称,可以用逗号分隔多个表。
  • --ignore-databases:指定要忽略的数据库名称,可以用逗号分隔多个数据库。
  • --ignore-tables:指定要忽略的表名称,可以用逗号分隔多个表。
  • --sync-to-master:指定从库要同步到主库的数据,这是最常用的场景。
  • --replicate:指定存储校验和结果的表名,默认是 percona.checksums。这个选项可以让 pt-table-sync 根据 pt-table-checksum 的结果来同步数据。
  • --execute:指定是否真正地执行 SQL 语句,默认是不执行,只打印。如果不指定这个选项,相当于 --dry-run 选项。
  • --print:指定是否打印 SQL 语句,默认是打印。如果不指定这个选项,相当于 --no-print 选项。

更多选项可以参考 pt-table-sync 文档

pt-table-sync 的使用示例

单主单从复制

在上一节中,我们使用 pt-table-checksum 发现了主从库上 test.t1 表的数据不一致。现在我们来使用 pt-table-sync 来修复这个问题。首先,我们在从库上运行 pt-table-sync 工具,指定要同步到主库的数据,以及校验和表的名称。我们先不指定 --execute 选项,只是查看需要执行的 SQL 语句。

# 在从库上运行 pt-table-sync
pt-table-sync --sync-to-master h=192.168.88.83,u=root,p= --databases test --tables t1 --replicate percona.checksums
# pt-table-sync output
UPDATE `test`.`t1` SET `name`='Bob' WHERE `id`=2 LIMIT 1;

这个输出告诉我们,为了修复数据不一致的问题,我们需要在从库上执行一个 UPDATE 语句,把 name 的值从 ‘Eve’ 改回 ‘Bob’。如果我们觉得这个 SQL 语句是正确的,我们可以再次运行 pt-table-sync 工具,这次加上 --execute 选项,来真正地执行 SQL 语句。

# 在从库上运行 pt-table-sync
pt-table-sync --sync-to-master h=192.168.88.83,u=root,p= --databases test --tables t1 --replicate percona.checksums --execute
# pt-table-sync output
# Syncing h=192.168.88.83,p=...,u=root
# DELETE REPLACE INSERT UPDATE ALGORITHM START    END      EXIT DATABASE.TABLE
#      0       0      0      1 Chunk     10:51:45 10:51:45 0    test.t1

这个输出告诉我们,pt-table-sync 已经成功地执行了一个 UPDATE 语句,来修复 test.t1 表的数据不一致。我们可以在主从库上再次查看 test.t1 表的数据,确认它们已经保持一致。

# 在主库上查看 test.t1 表的数据
mysql -h 192.168.88.82 -u root -p
mysql> select * from test.t1;
+----+---------+
| id | name    |
+----+---------+
|  1 | Alice   |
|  2 | Bob     |
|  3 | Charlie |
|  4 | David   |
+----+---------+
4 rows in set (0.00 sec)

# 在从库上查看 test.t1 表的数据
mysql -h 192.168.88.83 -u root -p
mysql> select * from test.t1;
+----+---------+
| id | name    |
+----+---------+
|  1 | Alice   |
|  2 | Bob     |
|  3 | Charlie |
|  4 | David   |
+----+---------+
4 rows in set (0.00 sec)

我们可以看到,主从库上的 test.t1 表的数据已经完全一致了。这就是 pt-table-sync 工具的基本用法。当然,它还可以应用于更复杂的复制拓扑和场景,例如多主多从、环形复制、双向复制等。有兴趣的读者可以参考 pt-table-sync 文档 来了解更多细节和示例。

总结

本文介绍了 Percona Toolkit 的两个组件:pt-table-checksum 和 pt-table-sync,它们可以帮助我们检测和修复 MySQL 主从库之间的数据不一致。我们通过一个单主单从复制的示例,演示了如何使用这两个工具,并介绍了一些常用的选项和注意事项。希望本文对 MySQL 复制的管理和维护有所帮助。

参考

pt-table-checksum — Percona Toolkit Documentation :

技术分享 | 数据校验工具 pt-table-checksum - 知乎 :

 MySQL replication primer:

pt-table-checksum,

pt-table-sync