作者:沈光宇

爱可生南区 DBA 团队成员,主要负责 MySQL 故障处理和性能优化。对技术执着,为客户负责。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


一、sync-diff-inspector简介

sync-diff-inspector 是由 PingCAP 开源的数据校验工具,用于校验MySQL/TiDB中两份数据是否一致。

主要功能如下:

  • 对比表结构和数据
  • 如果数据不一致,则生成用于修复数据的 SQL 语句
  • 支持不同库名或表名的数据校验
  • 支持分库分表场景下的数据校验
  • 支持 TiDB 主从集群的数据校验
  • 支持从 TiDB DM 拉取配置的数据校验

sync-diff-inspector 的使用限制

  • 对于 MySQL 和 TiDB 之间的数据同步不支持在线校验,需要保证上下游校验的表中没有数据写入,或者保证某个范围内的数据不再变更,通过配置 range 来校验这个范围内的数据。
  • FLOAT、DOUBLE 等浮点数类型在 TiDB 和 MySQL 中的实现方式不同,在计算 checksum 时会分别取 6 位和 15 位有效数字。如果不使用该特性,需要设置 ignore-columns 忽略这些列的检查。
  • 支持对不包含主键或者唯一索引的表进行校验,但是如果数据不一致,生成的用于修复的 SQL 可能无法正确修复数据。

本文将介绍使用 sync-diff-inspector 工具对两个 MySQL 实例中的数据进行校验,两个 MySQL 实例之间使用 DTS 工具来同步数据。

二、sync-diff-inspector工具下载安装

#sync-diff-inspector已集成在TiDB工具包中,直接下载TiDB工具包即可
shell> wget https://download.pingcap.org/tidb-community-toolkit-v6.4.0-linux-amd64.tar.gz
shell> tar zxvf tidb-community-toolkit-v6.4.0-linux-amd64.tar.gz
shell> ls -lh tidb-community-toolkit-v6.4.0-linux-amd64 | grep sync_diff_inspector
-rwxr-xr-x 1 tidb tidb  98M Nov 17 11:41 sync_diff_inspector
shell> ./sync_diff_inspector  -V
App Name: sync_diff_inspector v2.0
Release Version: v6.4.0
Git Commit Hash: f7e65073b35538def61ae094cd4a8e57e705344b
Git Branch: heads/refs/tags/v6.4.0
UTC Build Time: 2022-11-04 07:21:08
Go Version: go1.19.2

三、sync-diff-inspector工具使用示例

1.配置文件通用部分

shell> cat config.toml
check-thread-count = 4             # 检查数据的线程数量
export-fix-sql = true              # 如果开启,若表数据存在不一致,则输出用于修复的SQL语句
check-struct-only = false          # 只对比表结构而不对比数据
[data-sources]
[data-sources.mysql1]              # 上游MySQL数据库配置(源端)host = "10.186.65.57"          port = 3306user = "sgy"password = "admin"route-rules = ["rule1"]        # 映射匹配规则,通过配置相应的规则可以对单个、多个schema或table进行校验# 如有多个rule时,可配置成 ["rule1", "rule2"]
[data-sources.mysql2]              # 下游MySQL数据库配置(目标端)host = "10.186.65.89"port = 3309user = "sgy"password = "admin"

2.基于schema的数据校验

  • 对单个schema进行数据校验
#映射匹配规则部分,需要将此部分放到置配置文件通用部分的后面
[routes]                               # 映射关系,如上下游schema不同名可在此配置
[routes.rule1]schema-pattern = "sbtest"          # 匹配上游数据库的的库名target-schema = "sbtest"           # 匹配下游数据库的库名[task]output-dir = "./output"source-instances = ["mysql1"]   # 上游数据库,内容是 data-sources 声明的唯一标识 id,分库分表场景下支持多个上游数据库,如:["mysql10", "mysql20"]target-instance = "mysql2"      # 下游数据库,内容是 data-sources 声明的唯一标识 idtarget-check-tables = ["sbtest.*"]    # 需要比对的下游数据库的表# 进行数据校验
shell> ./sync_diff_inspector  --config=./config.toml
A total of 8 tables need to be comparedProgress [>------------------------------------------------------------] 0% 0/0
Comparing the table structure of ``sbtest`.`sbtest4`` ... equivalent     #表结构一致
Comparing the table structure of ``sbtest`.`sbtest5`` ... equivalent
.......................................................
Comparing the table data of ``sbtest`.`sbtest2`` ... equivalent          #表中数据一致
Comparing the table data of ``sbtest`.`sbtest8`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 8 table have been compared and all are equal.
You can view the comparision details through './output/sync_diff.log'
  • 对多个schema进行数据校验
#由于对多个schema进行数据校验,routes包含了rule1、rule2,配置文件通用部分需要做以下修改
[data-sources.mysql1] route-rules = ["rule1","rule2"]#映射匹配规则部分,需要将此部分放到配置文件通用部分的后面
[routes]
[routes.rule1]schema-pattern = "sbtest*"       #使用正则匹配sbtest开头的schema,如sbtest,sbtest1,sbtest2,sbtest3target-schema = "sbtest*"[routes.rule2]schema-pattern = "sgy"           #匹配schema:sgytarget-schema = "sgy"[task]output-dir = "./output"source-instances = ["mysql1"]     # 上游数据库,内容是 data-sources 声明的唯一标识 id,分库分表场景下支持多个上游数据库,如:["mysql10", "mysql20"]target-instance = "mysql2"        # 下游数据库,内容是 data-sources 声明的唯一标识 idtarget-check-tables = [ "sbtest*.*","sgy.*"]   #对源、目标实例中的sgy及以sbtest开头的schema所有表进行校验#进行数据校验
shell> ./sync_diff_inspector --config=./config.toml
A total of 24 tables need to be comparedProgress [>------------------------------------------------------------] 0% 0/0
Comparing the table structure of ``sgy`.`sbtest2`` ... equivalent
Comparing the table data of ``sgy`.`sbtest2`` ... equivalent
.......................................................
Comparing the table data of ``sbtest`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest3`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest2`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest1`.`sbtest2`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 24 table have been compared and all are equal.
You can view the comparision details through './output/sync_diff.log'

3.基于table的数据校验

  • 对单个table进行数据校验
#映射匹配规则部分,需要将此部分放置到配置文件通用部分的后面
[routes]
[routes.rule1]schema-pattern = "sbtest"target-schema = "sbtest"[task]output-dir = "./output"source-instances = ["mysql1"]      # 上游数据库,内容是 data-sources 声明的唯一标识 id,分库分表场景下支持多个上游数据库,如:["mysql10", "mysql20"] target-instance = "mysql2"         # 下游数据库,内容是 data-sources 声明的唯一标识 idtarget-check-tables = ["sbtest.sbtest1"]      #只校验表: sbtest.sbtest1#进行数据校验
shell> ./sync_diff_inspector --config=./config.toml
A total of 1 tables need to be comparedProgress [>------------------------------------------------------------] 0% 0/0
Comparing the table structure of ``sbtest`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest`.`sbtest1`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 1 table have been compared and all are equal.
You can view the comparision details through './output/sync_diff.log'
  • 对多个table进行数据校验
#对schema进行数据校验也是对多个table进行数据校验的一种,这里以指定多个具体表名为例
#由于对多个table进行数据校验,routes包含了rule1、rule2,配置文件通用部分需要做以下修改
[data-sources.mysql1] route-rules = ["rule1","rule2"]#映射匹配规则部分,需要将此部分放置到配置文件通用部分的后面
[routes]
[routes.rule1]schema-pattern = "sbtest*"target-schema = "sbtest*"[routes.rule2]schema-pattern = "sgy"target-schema = "sgy"[task]output-dir = "./output"source-instances = ["mysql1"]       # 上游数据库,内容是 data-sources 声明的唯一标识 id,分库分表场景下支持多个上游数据库,如:["mysql10", "mysql20"]target-instance = "mysql2"          # 下游数据库,内容是 data-sources 声明的唯一标识 id#只校验sbtest.sbtest8,sgy.sbtest4,sbtest1.sbtest1,sbtest2.sbtest2这四个表target-check-tables = [ "sbtest.sbtest8","sgy.sbtest4","sbtest1.sbtest1","sbtest2.sbtest2"]#进行数据校验
shell> ./sync_diff_inspector --config=./config.toml
A total of 4 tables need to be comparedProgress [>------------------------------------------------------------] 0% 0/0
Comparing the table structure of ``sbtest2`.`sbtest2`` ... equivalent
Comparing the table data of ``sbtest2`.`sbtest2`` ... equivalent
Comparing the table structure of ``sgy`.`sbtest4`` ... equivalent
Comparing the table structure of ``sbtest1`.`sbtest1`` ... equivalent
Comparing the table data of ``sgy`.`sbtest4`` ... equivalent
Comparing the table data of ``sbtest1`.`sbtest1`` ... equivalent
Comparing the table structure of ``sbtest`.`sbtest8`` ... equivalent
Comparing the table data of ``sbtest`.`sbtest8`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 4 table have been compared and all are equal.
You can view the comparision details through './output/sync_diff.log'
  • 对单表进行范围校验

#映射匹配规则部分,需要将此部分放置到配置文件通用部分的后面
[routes]
[routes.rule1]schema-pattern = "sbtest"target-schema = "sbtest"[task]output-dir = "./output"source-instances = ["mysql1"]      # 上游数据库,内容是 data-sources 声明的唯一标识 id,分库分表场景下支持多个上游数据库,如:["mysql10", "mysql20"]target-instance = "mysql2"         # 下游数据库,内容是 data-sources 声明的唯一标识 idtarget-check-tables = ["sbtest.sbtest1"]      # 指定校验目标实例上的sbtest.sbtest1表target-configs = ["config1"]                  # 对部分表的额外配置[table-configs.config1]
target-tables = ["sbtest.sbtest1"]                # 指定校验目标实例上的sbtest.sbtest1表
range = "id > 10 AND id < 100"                    # 指定校验目标表的具体范围,相当于SQL中的where条件
#数据校验见数据修复功能部分

4.数据修复功能

#为了演示数据修复,在目标端表中删除一些数据
shell> mysql -usgy -padmin -h 10.186.65.89 -P 3309 -e "delete from sbtest.sbtest1 where id in (11,22,33,44,55,66,77,88,99);"# 使用对单表进行范围校验配置,对sbtest.sbtest1表进行范围校验
shell> ./sync_diff_inspector  --config=./config.toml
A total of 1 tables need to be comparedComparing the table structure of ``sbtest`.`sbtest1`` ... equivalent     #sbtest.sbtest1表结构一致
Comparing the table data of ``sbtest`.`sbtest1`` ... failure             #sbtest.sbtest1表数据有差异
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
The data of `sbtest`.`sbtest1` is not equalThe rest of tables are all equal.
The patch file has been generated in 'output/fix-on-mysql2/'                 # 生成修复SQL输出到此目录
You can view the comparision details through './output/sync_diff.log'# 查看输出修复SQL
shell> cat output/fix-on-mysql2/sbtest\:sbtest1\:0\:0-0\:0.sql
-- table: sbtest.sbtest1
-- range in sequence: Full
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (11,50148,'69183965773-14680923687-92934799461-07606242492-78811530738-23241332728-92911647895-70477201282-85254929997-06214236905','33737501839-63208420999-35708593012-95906952636-68691055996');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (22,41538,'14140185946-16271766410-68340573738-46226480462-08989140676-29936780681-56784925909-45742390296-67137862436-18242076592','25112986220-19824650341-42825248958-70186905082-33867163574');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (33,50105,'48402160130-78797253227-05588677001-93556313541-39295466587-91364622063-58862572731-27837539373-64526858273-89372384747','72073637794-12055602042-16862397531-87496431032-85451396141');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (44,49917,'98096713237-15265478716-72025332919-62964308854-01270604715-12000922788-50929365082-43513513022-28543412388-57790852446','33907865533-62267179125-36062850111-84091551774-69847376840');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (55,50259,'68826640374-18002055907-53999869701-72145793168-90893177888-85273641163-24331745145-62755454379-79511152711-99618812770','02724012569-91405199011-30257626349-21678066897-42535351703');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (66,41995,'58396552954-26907336026-99506693837-77815822050-42927030403-40927779227-58101279219-11438233008-00344004393-35806649113','02348992414-65327666387-20632806790-74456238429-90933031209');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (77,49757,'73705207329-00308504929-05904865650-29498186065-09990420614-84131302024-40320022420-77358683577-34731688411-70665402097','92567035674-84728177369-79087155038-84461952379-45481760225');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (88,50497,'77112982215-98755241853-36424062009-45217742824-83650985380-60232607362-47569976121-30091332050-97996374956-97911403909','88977046077-43519705750-51246090615-77629911610-94055348738');
REPLACE INTO `sbtest`.`sbtest1`(`id`,`k`,`c`,`pad`) VALUES (99,49977,'63255973711-62890656114-72914458941-22277906368-32619356110-31219579310-16762665782-69578495131-76043317830-28240408380','08589883275-03392784968-00244590156-39735355951-95769933801');#将生成的修复SQL导入目标库
shell> mysql -usgy -padmin -h 10.186.65.89 -P 3309 < output/fix-on-mysql2/sbtest\:sbtest1\:0\:0-0\:0.sql
mysql: [Warning] Using a password on the command line interface can be insecure.#再次检验,发现数据已经一致
shell> ./sync_diff_inspector  --config=./config.toml
A total of 1 tables need to be comparedComparing the table structure of ``sbtest`.`sbtest1`` ... equivalent
Comparing the table data of ``sbtest`.`sbtest1`` ... equivalent
_____________________________________________________________________________
Progress [============================================================>] 100% 0/0
A total of 1 table have been compared and all are equal.
You can view the comparision details through './output/sync_diff.log'

四、相关问题

  • 修改配置文件后需要手动删除outputDir目录
shell> vim config.toml
shell> ./sync_diff_inspector --config=./config.toml     #将output-dir删除即可解决
Fail to initialize config.
failed to init Task: config changes breaking the checkpoint, please use another outputDir and start over again!
  • 表建议使用utf8mb4字符集,不支持MySQL8.0的utf8mb3字符集
mysql> select @@version;
+-----------+
| @@version |
+-----------+
| 8.0.30    |
+-----------+
1 row in set (0.00 sec)mysql> alter table sgy.sbtest4 CHARSET=utf8;
Query OK, 0 rows affected, 1 warning (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 1mysql> show create table sgy.sbtest4 \G
*************************** 1. row ***************************Table: sbtest4
Create Table: CREATE TABLE `sbtest4` (`id` int NOT NULL AUTO_INCREMENT,`k` int NOT NULL DEFAULT '0',`c` char(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',`pad` char(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT '',PRIMARY KEY (`id`),KEY `k_4` (`k`)
) ENGINE=InnoDB AUTO_INCREMENT=100001 DEFAULT CHARSET=utf8mb3
1 row in set (0.00 sec)   #执行数据校验时报错
shell> ./sync_diff_inspector --config=./config.toml
There is something error when initialize diff, please check log info in output/sync_diff.log#查看日志文件
shell> cat output/sync_diff.log  |grep utf8mb3
[2023/02/19 11:13:04.980 +08:00] [FATAL] [main.go:120] ["failed to initialize diff process"] [error="get table sgy.sbtest4's information error [parser:1115]Unknown character set: 'utf8mb3'\ngithub.com/pingcap/errors.

更详细的使用说明,请参考 sync-diff-inspector 官方文档:https://docs.pingcap.com/zh/tidb/stable/sync-diff-inspector-overview

技术分享 | 使用 sync_diff_inspector 对两个 MySQL 进行数据校验相关推荐

  1. Maatkit工具使用lt;一gt;之mysql主从数据校验工具

    mysql主从数据校验工具       mysql在5.1之前,其replication都是采用的STATEMENT模式,对表的数据是否一致要求并不严格,所以对数据一致性要求比较严格的应用,定期检查数 ...

  2. 【华为云技术分享】唐老师带你秒懂大数据,以及Spark和Flink在干啥咧

    [摘要] 花20分钟时间入门一个新领域,唐老师以一个生活中的例子,表达大数据框架Spark和Flink的各自特色.入门总结,请多指教. 作为网络老砖家(自封),唐老师本对大数据是一窍不通,在看完一系列 ...

  3. 技术分享 | 一款功能全面的 MySQL Shell 插件

    作者:杨涛涛 资深数据库专家,专研 MySQL 十余年.擅长 MySQL.PostgreSQL.MongoDB 等开源数据库相关的备份恢复.SQL 调优.监控运维.高可用架构设计等.目前任职于爱可生, ...

  4. mysql不同实例数据同步_两台Mysql数据库数据同步实现实例

    做开发的时候要做Mysql的数据库同步,两台安装一样的系统,都是FreeBSD5.4,安装了Apache 2.0.55和PHP 4.4.0,Mysql的版本是4.1.15,都是目前最新的版本. 1. ...

  5. 35岁技术人如何转型做管理?mysql删除数据语句

    阅读源码 程序员每天都和代码打交道.经过数年的基础教育和职业培训,大部分程序员都会「写」代码,或者至少会抄代码和改代码.但是,会读代码的并不在多数,会读代码又真正读懂一些大项目的源码的,少之又少.这也 ...

  6. 【华为云技术分享】云图说|第三方云厂商数据如何迁移至华为云OBS?真相在这里......

    很多客户有诉求将自己的业务从第三方云厂商迁移到华为云,发现自己的海量数据已经存放在了第三方云厂商的对象存储中,这部分数据怎么安全高效的迁移到华为云对象存储服务OBS呢? 别担心,一张云图说教会你将数据 ...

  7. 技术分享 | 两个单机 MySQL 该如何校验数据一致性

    作者:莫善 某互联网公司高级 DBA. 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源. 需求介绍 业务有两个 MySQL 集群是通过 MQ 进行同步 ...

  8. wps数据匹配怎么做_【VK技术分享】数据安全怎么做—静态数据的识别和治理

    前言 在当前的数据时代,随着云计算.大数据.AI等技术的不断发展,"数据"已经渗透到当今每一个行业和业务职能领域,成为重要的生产要素.数据的计量单位也至少是PB级别计算.这对于国家 ...

  9. mysql导出数据 程序_MySQL数据导出与导入程序代码

    Mysql Manual讲得很清楚.实现数据备份有两种方法,一是直接copy mysql data目录的数据文件.第二种就是mysqldmup. 第一方法,没什么可言,也就是写写脚本或是放置ftp上面 ...

最新文章

  1. 三维目标检测算法原理
  2. Python Excel 操作 | xlrd+xlwt 模块笔记
  3. 北京智源人工智能研究院2020年博士后招收简章
  4. Python Module_oslo.vmware_连接 vCenter
  5. Android使用addView动态加载布局文件
  6. Lua中的metatable
  7. django框架概述
  8. 说出来可能不信,现在酒厂都在招算法工程师
  9. ios审核一般要多久_水电施工要注意哪些问题?水电施工一般需要多久
  10. oracle虚拟件不活动,BOM 中的虚拟件
  11. Visual Studio 2008操作技巧
  12. c语言图书管理系统课设报告总结,c语言图书管理系统课设报告.docx
  13. ubuntu完全卸载mysql
  14. 世界七大数学难题与Hilbert的23个问题
  15. jemalloc 深入分析 之 Tcache 实现原理
  16. 孤军奋战的百合网 下一城会在哪?
  17. rockchip 瑞芯微 SDK 一些解释
  18. 换位思考的反思与总结
  19. openfire入门
  20. 计算机应用的高级职称,职称计算机应用能力要求相关政策规定

热门文章

  1. 吴刚:无线游戏的破局绝对在于专注
  2. Prompt 工程师是什么? 为什么要学习Prompt?
  3. 中年失业的你们在干嘛?
  4. 使用自签名证书进行TLS
  5. Commander.js中-h或help命令使用问题
  6. php触屏签字,触摸屏签名软件
  7. 世界杯看不明白?没事咱们还会画足球吗。
  8. 景区售票小程序系统需要开发哪些功能?
  9. 学生管理系统(Java版)(普通版(增删改查)、增强版(登录、注册、忘记密码))
  10. 产品(设备)履历本系统 (概要)