Percona Toolkit使用之pt-table-checksum

版权声明:本文为博主原创文章,转载敬请作出引用声明方便相互交流学习! https://blog.csdn.net/sweeper_freedoman/article/details/80201492

     pt-table-checksum的功能是校验MySQL复制完整性。

     用法如下:

pt-table-checksum [OPTIONS] [DSN]

     pt-table-checksum通过在master上执行checksum查询来实施在线复制一致性检查,如果在replica上产生不同的checksum结果,replica就和master数据不一致。可选项DSN(MySQL连接访问)指定master服务器。如果发现不一致、或者产生警告和报错,该工具的退出状态为非0。

     以下命令会连接到localhost上的复制master,校验每张表,然后报告每一个检测到的replica的校验结果:

pt-table-checksum

     该工具致力于有效地找出数据的不一致。如果数据是不一致的,你可以使用pt-table-sync(https://blog.csdn.net/sweeper_freedoman/article/details/80235177)工具解决。

     pt-table-checksum设计用于在几乎所有的情况下默认做正确的事情。存在疑问时,使用--explain选项查看该工具如何校验表。以下是该工具如何作用的高层次概观。

     较于旧版本的pt-table-checksum,现在该工具专注于单个目的,不再有大量复杂性和对多种不同校验技术的支持。它只在一台服务器上执行校验查询,然后校验查询通过复制流入到replica再执行。如果你需要旧版特性,可以使用Percona Toolkit version 1.0。

     pt-table-checksum连接到你指定的服务器,查找匹配你指定筛选的库表(如果指定了的话)。它一次作用于一张表,所以不会占用大量内存,开始校验前也不会做很多工作。这使它在非常大的服务器上可用。我们已经将它使用到有成百上千库表、万亿行记录的服务器。无论多大的服务器,pt-table-checksum运行得同样好。

     它可以在非常大的表上工作的一个原因是它将每张表的记录分割成块,然后用单个“ REPLACE …SELECT ”查询来计算每个记录块的checksum。它会改变块大小来使checksum查询在设想大小的时间内运行。将表分块而不是对每个表进行单个大查询的目的就是确保checksum查询是非入侵式的,不会导致服务器过大的复制延迟和负载。这就是为什么每个块的目标时间默认是0.5秒的原因。

     该工具对服务器能够多快地执行校验查询进行追踪,然后当它了解到更多有关服务器的性能后,对块大小进行调整。它使用指数衰减加权平均来保持块大小稳定,但是出于任何原因,如果在checksum查询时服务器的性能改变,它会保持响应。这意味着该工具可以快速自我调节,例如如果你的服务器在流量高峰或者后台任务而变得高负载时。

     分块是通过一种在Percona Toolkit其他工具中曾被称为“ nibbling ”的技术实现的。例如它和用于pt-archiver(https://www.percona.com/doc/percona-toolkit/LATEST/pt-archiver.html)的是相同的技术。在旧版本pt-table-checksum中遗留使用的分块算法被移除,因为它们不能生成预想大小的块,而且在很多表上不能很好地工作。将表分割成块的全部所需就是索引(最好是主键或者唯一索引)。如果没有索引,而表含有适宜的小数目记录,工具就会在单个块里面校验该表。

     pt-table-checksum包含很多其他的防护措施来确保不影响服务器的任何操作,包括replica。为了实现这一点,pt-table-checksum自动检测和连接replica。(这如果失败了,你可以使用--recursion-method选项给它一个提示)。

     该工具持续监视replica。如果有replica落后复制太远,pt-table-checksum挂起以使其追赶上来。如果replica出错或者复制停止,pt-table-checksum中断然后等待。另外,pt-table-checksum会查找问题产生的常见原因,例如复制筛选过滤,除非你强制它,否则它拒绝操作。复制筛选过滤是危险的,因为pt-table-checksum执行的查询可能与其发生冲突而导致复制失败。

     pt-table-checksum会验证块的大小不会太大,以安全地进行checksum。它对每个块执行一个EXPLAIN查询,然后忽略那些可能会大于期望行数的块。你可以使用--chunk-size-limit选项来配置该防护措施的灵敏度。如果一张表因为包含的记录量小而将被置于单个块中checksum,pt-table-checksum会去额外验证该表在replica上不会过大。这避免了以下情况:表在master上空的但在replica上非常大,然后在单个大查询里面checksum的话,就会导致一个非常长的复制延迟。

     还有一些其他的防护措施。例如,pt-table-checksum会设置其会话级别的innodb_lock_wait_timeout为1秒,以便如果出现锁等待,它会成为牺牲者而不是导致其他查询超时。另一个防护措施检查数据库服务器上的负载,如果负载太高就会中断。对于如何去做这一点并没有一个正确的答案,默认情况下如果并行查询超过25个pt-table-checksum就会挂起。你可以使用--max-load选项设定一个就你的服务器而言的稳健值。

     checksum操作通常是让步于服务器上其他工作的低优先级任务。然而,一个必须频繁重启的工具是很难使用的。于是,pt-table-checksum对错误有很强的适应能力。例如,如果数据库管理员出于任何原因需要杀死pt-table-checksum的查询,这不会是一个致命错误。用户经常使用pt-kill(https://blog.csdn.net/sweeper_freedoman/article/details/79838375)来杀死长时间执行的checksum查询。该工具会尝试再执行一次被杀死的查询,如果还执行失败,它会转移到该表的下一个块。如果发生锁等待超时,使用同样的行为。如果出现该错误,工具会输出一个警告,但每张表只打印一次。如果到服务器的连接失败,pt-table-checksum会尝试去重新连接然后继续工作。

     如果pt-table-checksum遇到使它完全停止的状况,可以方便地使用--resume选项恢复。它会从它处理的最近一个表的最近一个块开始。你也可以使用CRTL-C安全停止该工具。它将完成当前正在处理的块然后退出。之后你仍然可以恢复它。

     当pt-table-checksum完成一张表中所有块的checksum后,它会挂起,然后等待所有检测到的replica执行完checksum查询。查询一旦执行结束,它会检查所有的replica来看它们是否同master具有相同的数据,然后打印出一行包含结果的输出。

     该工具在耗时操作时打印进度指示器。每个表checksum时它都会打印一个进度指示器。进度计算自表中记录的预估值。当挂起以等待复制追赶上来以及进行replica与master不一致检查等待时,它也会打印进度报告。你可以使用--quiet选项让输出不那么冗长。

     如果你愿意,你可以手动查询checksum表来得到一份哪些表和块与master不一致的报告。以下查询会汇报每个有不一致的库表,以及可能受影响的块和记录的数量的汇总信息。该查询中引用的表为checksum表,是checksum结果存储的地方。该表中的每一行都包含服务器里某个表的一个块的checksum数据。

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-checksum默认使用CRC32进行checksum。CRC32不是一个密码算法因此它容易发生冲突。但是另一方面,CRC32算法相较MD5和SHA1更快,也是非CPU密集型的。

     pt-table-checksum需要基于行的复制(statement-based replication),它在master上设置binlog_format=STATEMENT,但是由于MySQL的限制,replica并不遵循该修改。因此,checksum查询不会复制到使用基于行的复制(row-based replication),是之后replica的master的replica(链式复制拓扑结构中扮演两种角色的中间replica:既是之前master的replica,又是之后replica的master)。该工具自动检查所有服务器的binlog_format。参考--[no]check-binlog-format。

     该工具假定master和所有replica上的库表是相同的。复制会失败,例如,如果replica没有master上存在的库(并且该库被执行了checksum),或者如果replica上表的结构与其在master上的不一致。

     该工具打印表格化结果,每张表一行。错误、警告以及进度报告会打印到标准误。参考--quiet选项。当工具完成对表的checksum,该表的结果就会被打印输出。

            TS ERRORS  DIFFS  ROWS  CHUNKS SKIPPED    TIME TABLE
10-20T08:36:50      0      0   200       1       0   0.005 db1.tbl1
10-20T08:36:50      0      0   603       7       0   0.035 db1.tbl2
10-20T08:36:50      0      0    16       1       0   0.003 db2.tbl3
10-20T08:36:50      0      0   600       6       0   0.024 db2.tbl4

  • TS

工具完成对该表的checksum时的时间戳(不包含年份)。

  • ERRORS

对该表执行checksum时发生的错误和警告计数。当该表在执行时错误和警告也会打印到标准误。

  • DIFFS

一个或多个replica上异于master的块计数。如果指定--no-replicate-check选项,该列将一直为0。如果指定--replicate-check-only选项,只有出现不一致的表才会被打印输出。

  • ROWS

表中被查询和checksum的行数。它可能和你使用where选项得到的该表的行数不一致。

  • CHUNKS

该表被分割的块数。

  • SKIPPED

由于这些问题中的一个或多个而跳过的块数。自pt-table-checksum 2.2.5版本起,块跳过将产生一个非0退出状态。

  1. MySQL没有使用--chunk-index
  2. MySQL没有使用全部块索引(--[no]check-plan)
  3. 块大小大于--chunk-size * --chunk-size-limit
  4. 锁等待超时(--retries)
  5. checksum查询被杀死(--retries)
  • TABLE

被checksum的库表。

如果指定--replicate-check-only选项,只有检测到的replica上的checksum不一致才会被打印输出。输出是不一样的:一个replica一段,一个checksum不一致一行,并且值以空格分割。

Differences on h=127.0.0.1,P=12346
TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY
db1.tbl1 1 0 1 PRIMARY 1 100
db1.tbl1 6 0 1 PRIMARY 501 600

Differences on h=127.0.0.1,P=12347
TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY
db1.tbl1 1 0 1 PRIMARY 1 100
db2.tbl2 9 5 0 PRIMARY 101 200

    ①TABLE

与master不一致的库表。

     ②CHUNK

该表与master不一致的块号。

     ③CNT_DIFF

replica上的块行数减去master上的块行数。

     ④CRC_DIFF

如果replica上该块的CRC和master上该块的CRC不一致则为1;否则为0。

     ⑤CHUNK_INDEX

对该表分块时使用的索引。

     ⑥LOWER_BOUNDARY

定义该块下界的索引值。

     ⑦UPPER_BOUNDARY

定义该块上界的索引值。

     pt-table-checksum有三种可能的退出状态:0、255、以及其他值是带有不同问题标志的位掩码。0退出状态指示没有错误、警告、checksum不一致、跳过块或表。255退出状态指示致命错误。换句话说:该工具死了或者崩溃了。该错误会打印输出到STDERR。如果退出状态不是0或者255,则其值为带有以下标志的位掩码。

FLAG              BIT VALUE  MEANING
================  =========  ==========================================
ERROR                     1  A non-fatal error occurred
ALREADY_RUNNING           2  --pid file exists and the PID is running
CAUGHT_SIGNAL             4  Caught SIGHUP, SIGINT, SIGPIPE, or SIGTERM
NO_SLAVES_FOUND           8  No replicas or cluster nodes were found
TABLE_DIFF               16  At least one diff was found
SKIP_CHUNK               32  At least one chunk was skipped
SKIP_TABLE               64  At least one table was skipped

     以下为个人本地环境的测试数据。由于MySQL配置的是基于GTID的新复制技术,pt-table-checksum采用当前最新版3.0.9,当前环境的问题是需要手动设置一下binlog_format才能checksum出master与slave之间的数据不一致。

     首先是master上不一致的表。

mysql> SELECT * FROM `player`.`player_def`;
+----+--------+-------+-------------+
| id | number | name  | role        |
+----+--------+-------+-------------+
|  1 |      1 | hachi | GK          |
|  2 |      2 | ni    | left back   |
|  3 |      3 | san   | center back |
|  4 |      4 | yon   | center back |
|  5 |      5 | go    | right back  |
+----+--------+-------+-------------+
5 rows in set (0.00 sec)

     然后是slave上同一张表的情况(其实是张清除了数据的空表)。

mysql> SELECT * FROM `player`.`player_def`;
Empty set (0.00 sec)

     执行pt-table-checksum检查不一致性。

mysql> 
mysql> SHOW VARIABLES LIKE 'gtid_mode';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| gtid_mode     | ON    |
+---------------+-------+
1 row in set (0.01 sec)

mysql> SHOW VARIABLES LIKE 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.01 sec)

mysql> SET GLOBAL binlog_format = 'STATEMENT';                                                                                         
Query OK, 0 rows affected (0.00 sec)

mysql> system pt-table-checksum -h192.168.112.129 -P3306 -uroot -p123456 -dplayer --no-check-binlog-format --no-check-replication-filters
Checking if all tables can be checksummed ...
Starting checksum ...
            TS ERRORS  DIFFS     ROWS  CHUNKS SKIPPED    TIME TABLE
05-08T00:12:19      0      0        1       1       0   0.019 player.heartbeat
05-08T00:12:19      0      0        5       1       0   0.017 player.player
05-08T00:12:19      0      1        5       1       0   0.017 player.player_def
05-08T00:12:19      0      0        2       1       0   0.021 player.query_review
mysql> system pt-table-checksum -h192.168.112.129 -P3306 -uroot -p123456 -dplayer --no-check-binlog-format --no-check-replication-filters --replicate-check-only
Checking if all tables can be checksummed ...
Starting checksum ...
Differences on bilery.zoo
TABLE CHUNK CNT_DIFF CRC_DIFF CHUNK_INDEX LOWER_BOUNDARY UPPER_BOUNDARY
player.player_def 1 -5 1   

mysql> SET GLOBAL binlog_format = 'ROW';
Query OK, 0 rows affected (0.00 sec)

mysql> 

     参考:

https://www.percona.com/doc/percona-toolkit/LATEST/pt-table-checksum.html

猜你喜欢

转载自blog.csdn.net/sweeper_freedoman/article/details/80201492
今日推荐