介绍
- pt-table-checksum 和 pt-table-sync 是 percona 公司发布的、检查 MySQL 主从数据库数据一致性校验的工具。
- pt-table-checksum 利用 MySQL 复制原理,在主库执行校验和计算,并对比主从库校验和,由此判断主从库数据是否一致。
- 如果发现数据不一致,或者命令执行报 warning 或 error,则返回状态值为非0。
- pt-table-checksum 用于找出数据差异,pt-table-sync 用于修复数据差异。
- 即使数据库有几十万张表,数万亿行数据,pt-table-checksum 运行也很良好。
工作原理
- pt-table-checksum 运行时,将每张表分成多个 chunk,并使用 replace ... select 查询,对每个 chunk 进行 checksum 计算。
- 它可以改变 chunk size,以使校验和查询在所需的时间内运行,每个 chunk 的目标时间默认是 0.5 秒。
- 它可以跟踪服务器执行查询的速度,并在服务器性能负载过重时,如流量高峰或后台任务时,自动调节 chunk size。
- 执行校验的表要有主键或唯一索引,这样校验的速度才会快。
- chunk size 可以使用 --chunk-size-limit 设置 chunk 的最大值。
- 运行时,它会设置 session 级的 innodb_lock_wait_time_out 为 1,如果存在锁等待的话,它会释放锁,保证数据库能够正常读写。
- 默认一张表同时有25个查询时,它将暂停。查询数可以使用 --max-load 设置。
- 如果它的查询被 kill 的话,它将重试一次,如果再次失败,它将跳到下一个 chunk。如果锁等待超时,它会执行相同的行为。如果发生此类错误,将打印 warning,但是每张表只会打印一次。如果网络中断,它会尝试重连并继续执行。
- 如果 pt-table-checksum 异常终止了,可以加上 --resume 选项恢复它,它将从上次处理的最后一个 chunk 开始。可以随时执行 CTRL+C 手动停止,并再次恢复。
- 当检查完所有表块的校验和后,它将暂停并等待所有从库执行完校验和查询。随后检查所有的从库与主库的数据是否相同,并打印一行结果。
- 可以手动执行如下查询,查询校验和信息
1 2 3 4 5 6 7 | 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 需要基于 statement 的复制,运行时需要在 master 上设置 binlog_format=statement,从库不接受此项更改。
- 工具运行时会检查所有库的 binlog 格式。
- 如果复制从库没有主库上的校验和架构、或者主从库的表结构不一致,复制会中断。
退出状态
- 0 为正常,没有 warning、error、校验和差异、或跳过的表、块。
- 255 为严重错误,
- 其他大于 0,小于 255 的值,都表示一种异常,可以查看手册。
选项
选项名 | 说明 | 默认值 | 类型 | 组别 |
--ask-pass | 执行时手动输入密码 | |||
--[no]check-binlog-format | 检查所有库的 binlog_format 值 | yes | ||
--binary-index | 改变 --create-replicate-table 创建的表类型,改成 BLOB 类型,用于字符集非标准字符集时。 | |||
--check-interval | 1 | 阈值 | ||
--[no]check-plan | 工具使用了几种启发式方法判断执行计划是否有错,如果执行计划有错误,将跳过表块,开启会增加执行时间 | yes | ||
--[no]check-replication-filters | 如果主库或从库设置了binlog_ignore_db 或 replicate_do_db 的过滤选项,因为不能保证查询和校验和不会导致复制中断,所以执行工具会因报错而终止。 使用工具使要确保没有过滤参数,再开启此选项。 | yes | 安全 | |
--check-slave-lag | 工具会监视所有从库的延迟,如果某个从库延迟超过 --max-lag 的值,则暂停执行校验和,直到从库的延迟小于 --max-lag 的值。 | string | 阈值 | |
--[no]check-slave-tables | 检查所有从库的表都存在、且表的列与主库的列相同,避免因为主从库表结构不一致导致复制中断。 同样是在确保主从库表结构一致时,再开启此选项。 | yes | 安全 | |
--chunk-index | 为工具设置 chunk 时强制指定的索引,指定的索引会被工具以 FORCE INDEX 子句写入 SQL 语句中。注意手动选择索引可能导致性能下降。 当默认索引不合适可以手动指定索引,但当手动指定索引不存在,工具将回归默认方式选择索引。 | string | ||
--chunk-index-columns | 设置复合索引的最左索引列的列数。 复合索引包含列数过多时,可能导致 mysql 的扫描范围过大或执行计划错误,此选项可以提高索引选择效率。 通常在包含4个列或4个以上的列时使用。 | int | ||
--chunk-size | 为执行每次校验和的SQL设置rows,后缀可以为 k、m、g。通常不用设置此项,设置 --chunk-time 更有效。 设置此项会导致动态调整 chunk 失效,并使每个 chunk 都等于设置的值。另外,如果设置5000,但某个where 子句只能匹配1000,那么这个chunk可能会被跳过。 设置较小会导致校验变慢,因为需要设置 --[no]check-plan | 1000 | size | |
--chunk-size-limit | 块大小限制倍数。因为工具获取 chunk 的行数,是来自执行计划中估计的行数,而非准确值。 如果该 chunk 超过了 1000 * limit 的大小,工具将跳过该块。 如果 limit 为1,表示任何 chunk 都不能大于 --chunk-size;如果 limit 为0,则表示没有限制。 | 2.0 | float | 安全 |
--chunk-time | 动态调整块大小,以便每个校验和查询都需要这么长的时间来执行。如果调整该参数为0,将不会自动调整块大小。 | 0.5 | float | |
--columns | 缩写 -c。如果校验的表不包含指定的列,则跳过该表。 此选项适用于所有表,因此它实际上只在对一个表进行校验和时才有意义,除非这些表有一组公共列。 | array | 过滤器 | |
--config | 读取以逗号分割的配置文件列表,如果配置该选项,该选项必须是第一个参数。 | array | 配置 | |
--[no]create-replicate-table | 如果不存在 replicate 库和表,则创建它们。 | yes | ||
--databases | 缩写 -d。仅对指定的库列表进行校验和。 | hash | 过滤器 | |
--databases-regex | 只校验 Perl 正则匹配的数据库。 | string | 过滤器 | |
--defaults-file | 从指定的文件读取 mysql 参数。该文件必须包含绝对路径。 | string | 连接 | |
--[no]empty-replicate-table | 对表进行校验和之前,删除复制表之前的校验和结果。删除不是执行 truncate,而是检查到对应表时再删除对应结果。 表不会自动清空,为了下次执行时可以使用之前的结果。可以手动清空。 | yes | ||
--engines | 缩写 -e。只检查指定引擎的表。 | hash | 过滤器 | |
--explain | 显示计划,但不执行查询、校验和。如果指定2次,则打印每个 chunk 的上下边界,但不执行查询、校验和。 | 0 | 累计值 | 输出 |
--float-precision | 浮点和双数到字符串转换的精度。使用MySQL中的ROUND() 函数将浮点值和双精度值舍入到小数点后指定的位数。 | int | ||
--function | 校验和的 hash 函数(FNV1A_64、murtur_Hash、SHA1、MD5、CRC32等)默认是 crc32,也可以自己定义,但是函数必须是 mysql 内部支持的。mysql 内部没有很好的哈希函数,crc32 可能会有冲突,但是 md5 和 sha1 会非常占用 cpu。 | string | ||
--host | 缩写 -h。默认 localhost。 | string | 连接 | |
--ignore-columns | 计算校验和时忽略此以逗号分隔的列列表。如果表的所有列都按–忽略列筛选,则将跳过该表。 | hash | 过滤器 | |
--ignore-databases | 忽略此以逗号分隔的数据库列表。 | hash | 过滤器 | |
--ignore-databases-regex | 忽略名称与此Perl正则表达式匹配的数据库。 | string | 过滤器 | |
--ignore-engines | 忽略此以逗号分隔的存储引擎列表。 | FEDERATED,MRG_MyISAM | hash | 过滤器 |
--ignore-tables | 忽略这个用逗号分隔的表列表。 | hash | 过滤器 | |
--ignore-tables-regex | 忽略名称与Perl regex匹配的表。 | string | 过滤器 | |
--max-lag | 暂停校验和,直到所有副本的延迟小于此值。工具使用 Seconds_Behind_Master 来比较。如果任何从库的延迟时间超过这个值,则工具将休眠 --check-interval 秒。可以指定 --check-slave-lag,则只检查指定服务器的 lag,而不是所有从库。 | 1s | time | 阈值 |
--max-load | 工具检查每个块之后,执行 show global status,如果任何状态变量高于阈值,则暂停。该选项接受以逗号分隔的MySQL状态变量列表来检查阈值。每个变量后面都可以有一个可选的=MAX_VALUE。如果没有给出,工具通过检查当前值并将其增加20%来确定阈值。如 Threads_running=100,高于120时暂停,小于120时恢复运行。 | Threads_running=25 | array | 阈值 |
--password | 缩写 -p。连接时使用的密码。 | string | 连接 | |
--pause-file | 当此参数指定的文件存在时,将暂停执行。 | string | ||
--pid | 创建指定的 pid 文件。如果pid 文件已经存在,并且它包含的 pid 与当前 pid 不同,则该工具不会启动。 但是,如果 pid 文件存在并且它包含的 pid 不再运行,则该工具将用当前 pid 覆盖该 pid 文件。当工具退出时,将自动删除 pid 文件。 | string | ||
--plugin | 定义一个 pt_table_checksum_plugin 类的模块。perl 模块可以挂载到工具的很多部分中。 | string |