一、背景
由DM工具同步MySQL数据到TiDB,有时候会出现数据不一致的情况,这时候我们就需要一种检验工具来进行这种检验,官方提供了这样一种检验工具
二、工具下载与使用
1.下载
wget https://download.pingcap.org/tidb-enterprise-tools-nightly-linux-amd64.tar.gz
2.解压
tar zxvf tidb-enterprise-tools-nightly-linux-amd64.tar.gz
3.进入到对应的目录
cd tidb-enterprise-tools-nightly-linux-amd64/bin
4.编辑配置文件
# Diff Configuration.
######################### Global config #########################
# 日志级别,可以设置为 info、debug
log-level = "info"
# sync-diff-inspector 根据主键/唯一键/索引将数据划分为多个 chunk,
# 对每一个 chunk 的数据进行对比。使用 chunk-size 设置 chunk 的大小
chunk-size = 1000
# 检查数据的线程数量
check-thread-count = 4
# 抽样检查的比例,如果设置为 100 则检查全部数据
sample-percent = 100
# 通过计算 chunk 的 checksum 来对比数据,如果不开启则逐行对比数据
use-checksum = true
# 如果设置为 true 则只会通过计算 checksum 来校验数据,如果上下游的 checksum 不一致也不会查出数据再进行校验
only-use-checksum = false
# 是否使用上次校验的 checkpoint,如果开启,则只校验上次未校验以及校验失败的 chunk
use-checkpoint = true
# 不对比数据
ignore-data-check = false
# 不对比表结构
ignore-struct-check = false
# 保存用于修复数据的 sql 的文件名称
fix-sql-file = "fix.sql"
######################### Tables config #########################
# 如果需要对比大量的不同库名或者表名的表的数据,或者用于校验上游多个分表与下游总表的数据,可以通过 table-rule 来设置映射关系
# 可以只配置 schema 或者 table 的映射关系,也可以都配置
#[[table-rules]]
# schema-pattern 和 table-pattern 支持通配符 *?
#schema-pattern = "test_*"
#table-pattern = "t_*"
#target-schema = "test"
#target-table = "t"
# 配置需要对比的*目标数据库*中的表
[[check-tables]]
# 目标库中数据库的名称
schema = "test"
# 需要检查的表
tables = ["test1", "test2", "test3"]
# 支持使用正则表达式配置检查的表,需要以‘~’开始,
# 下面的配置会检查所有表名以‘test’为前缀的表
# tables = ["~^test.*"]
# 下面的配置会检查配置库中所有的表
# tables = ["~^"]
# 对部分表进行特殊的配置,配置的表必须包含在 check-tables 中
[[table-config]]
# 目标库中数据库的名称
schema = "test"
# 表名
table = "test3"
# 指定用于划分 chunk 的列,如果不配置该项,sync-diff-inspector 会选取一个合适的列(主键/唯一键/索引)
index-field = "id"
# 指定检查的数据的范围,需要符合 sql 中 where 条件的语法
range = "age > 10 AND age < 20"
# 如果是对比多个分表与总表的数据,则设置为 true
is-sharding = false
# 在某些情况下字符类型的数据的排序会不一致,通过指定 collation 来保证排序的一致,
# 需要与数据库中 charset 的设置相对应
# collation = "latin1_bin"
# 忽略某些列的检查,例如 sync-diff-inspector 目前还不支持的一些类型(json,bit,blob 等),
# 或者是浮点类型数据在 TiDB 和 MySQL 中的表现可能存在差异,可以使用 ignore-columns 忽略检查这些列
# ignore-columns = ["name"]
# 下面是一个对比不同库名和表名的两个表的配置示例
[[table-config]]
# 目标库名
schema = "test"
# 目标表名
table = "test2"
# 非分库分表场景,设置为 false
is-sharding = false
# 源数据的配置
[[table-config.source-tables]]
# 源库的实例 id
instance-id = "source-1"
# 源数据库的名称
schema = "test"
# 源表的名称
table = "test1"
######################### Databases config #########################
# 源数据库实例的配置
[[source-db]]
host = "127.0.0.1"
port = 3306
user = "root"
password = "123456"
# 源数据库实例的 id,唯一标识一个数据库实例
instance-id = "source-1"
# 使用 TiDB 的 snapshot 功能,如果开启的话会使用历史数据进行对比
# snapshot = "2016-10-08 16:45:26"
# 设置数据库的 sql-mode,用于解析表结构
# sql-mode = ""
# 目标数据库实例的配置
[target-db]
host = "127.0.0.1"
port = 4000
user = "root"
password = "123456"
# 使用 TiDB 的 snapshot 功能,如果开启的话会使用历史数据进行对比
# snapshot = "2016-10-08 16:45:26"
# 设置数据库的 sql-mode,用于解析表结构
# sql-mode = ""
5.开始使用
./bin/sync_diff_inspector --config=./config.toml
该命令最终会在日志中输出一个检查报告,说明每个表的检查情况。如果数据存在不一致的情况,sync-diff-inspector 会生成 SQL 修复不一致的数据,并将这些 SQL 语句保存到 fix.sql
文件中。
日志
sync-diff-inspector 会在运行时定期(间隔 10s)输出校验进度到日志中,格式如下:
[2020/11/12 17:47:00.170 +08:00] [INFO] [checkpoint.go:276] ["summary info"] [instance_id=target] [schema=test] [table=test_table] ["chunk num"=1000] ["success num"=80] ["failed num"=1] ["ignore num"=0]
- chunk num:总共需要校验的 chunk 数量。
- success num:已经校验数据一致的 chunk 数量。
- failed num:校验失败的 chunk 数量。校验时遇到错误和数据不一致两种情况都属于校验失败。
- ignore num:被忽略校验的 chunk 数量。当配置项
sample-percent
的值小于100
时,sync-diff-inspector 会采用抽样的方式校验数据,这样就会有部分 chunk 被忽略校验。
校验结果
当校验结束时,sync-diff-inspector 会输出一份校验报告。
- 数据校验一致的日志示例如下:
[2020/11/12 17:47:00.174 +08:00] [INFO] [report.go:80] ["check result summary"] ["check passed num"=1] ["check failed num"=0]
[2020/11/12 17:47:00.174 +08:00] [INFO] [report.go:87] ["table check result"] [schema=test] [table=test_table] ["struct equal"=true] ["data equal"=true]
[2020/11/12 17:47:00.174 +08:00] [INFO] [main.go:75] ["check data finished"] [cost=353.462744ms]
[2020/11/12 17:47:00.174 +08:00] [INFO] [main.go:69] ["check pass!!!"]
- 数据校验不一致或者遇到错误时的日志示例如下:
[2020/11/12 18:16:17.068 +08:00] [INFO] [checkpoint.go:276] ["summary info"] [instance_id=target] [schema=test] [table=test1] ["chunk num"=1] ["success num"=0] ["failed num"=1] ["ignore num"=0]
[2020/11/12 18:16:17.071 +08:00] [INFO] [report.go:80] ["check result summary"] ["check passed num"=0] ["check failed num"=1]
[2020/11/12 18:16:17.071 +08:00] [INFO] [report.go:87] ["table check result"] [schema=test] [table=test_table] ["struct equal"=true] ["data equal"=false]
[2020/11/12 18:16:17.071 +08:00] [INFO] [main.go:75] ["check data finished"] [cost=319.849706ms]
[2020/11/12 18:16:17.071 +08:00] [WARN] [main.go:66] ["check failed!!!"]
校验通过和未通过的表的个数打印在 check result summary
中。所有表的校验结果的打印在 table check result
中。
查看具体哪张表不一致
cat same.log |grep '"data equal"=false'
注意事项
- sync-diff-inspector 在校验数据时会消耗一定的服务器资源,需要避免在业务高峰期间校验。
- TiDB 使用的 collation 为
utf8_bin
。如果对 MySQL 和 TiDB 的数据进行对比,需要注意 MySQL 中表的 collation 设置。如果表的主键/唯一键为 varchar 类型,且 MySQL 中 collation 设置与 TiDB 不同,可能会因为排序问题导致最终校验结果不正确,需要在 sync-diff-inspector 的配置文件中增加 collation 设置。 - sync-diff-inspector 会优先使用 TiDB 的统计信息来划分 chunk,需要尽量保证统计信息精确,可以在业务空闲期手动执行
analyze table {table_name}
。 - table-rule 的规则需要特殊注意,例如设置了
schema-pattern="test1"
,target-schema="test2"
,会对比 source 中的test1
库和 target 中的test2
库;如果 source 中有test2
库,该库也会和 target 中的test2
库进行对比。 - 生成的
fix.sql
仅作为修复数据的参考,需要确认后再执行这些 SQL 修复数据。
官网链接:https://docs.pingcap.com/zh/tidb/stable/sync-diff-inspector-overview