1. 前言

有时需要比较MySQL不同数据库间结构相同的表数据是否相同,例如在测试环境与生产环境之间比较,或多个测试环境之间比较,以下提供一种通用的快速比较方式。

2. 比较方法

对于需要比较数据的数据库表,将每行中关心的字段进行拼接,计算其HASH值;再根据主键或其他字段对每行的HASH值进行排序,并将每行的HASH值拼接,对拼接结果计算最终的HASH值。

在比较MySQL不同数据库间结构相同的表数据是否相同时,比较以上HASH值即可。若最终的HASH值不同,则说明数据库表中的数据不同;若最终的HASH值相同 ,则说明数据库表中的数据大概率相同。

3. 使用的MySQL函数

3.1. HASH函数

参考 https://dev.mysql.com/doc/refman/5.6/en/encryption-functions.html ,MySQL提供了MD5()、SHA1()、SHA2()等函数用于计算HASH。

MD5的碰撞概率比SHA1高,SHA2计算结果长度至少为224,不便于比较。因此选择SHA1()函数计算HASH,其结果长度为40。

以下语句及执行结果如下:

select sha1('a');
86f7e437faa5a7fce15d1ddcb9eaeaea377667b8

3.2. 拼接同一行中的字段

参考 https://dev.mysql.com/doc/refman/5.6/en/string-functions.html#function_concat ,使用CONCAT()函数可拼接字段,当某个字段为NULL时,返回NULL。因此不能使用CONCAT()函数进行拼接。

以下语句及执行结果如下:

select concat('1',null,'2');
null

参考 https://dev.mysql.com/doc/refman/5.6/en/string-functions.html#function_concat-ws ,使用CONCAT_WS()函数可以拼接字段,功能与CONCAT()函数类似,可以使用第1个参数指定剩余参数间的分隔符。当参数1为NULL时,结果也为NULL。

CONCAT()函数不会跳过空字符串’’,但会跳过参数1之后的NULL值。

以下语句及执行结果如下:

select concat_ws(':', '1', '2', '3');
1:2:3select concat_ws(':','1',null,'2',null,null,'3');
1:2:3

若某个需要拼接的字段为二进制格式,可使用HEX()、TO_BASE64()等函数对其进行编码,使其变为字符串格式。

以下语句及执行结果如下:

select hex(0x0a);
0Aselect to_base64(0x0a);
Cg==

3.3. 拼接不同行的数据

参考 https://dev.mysql.com/doc/refman/5.6/en/aggregate-functions.html#function_group-concat ,使用GROUP_CONCAT()函数,可以将一组非空值拼接,返回一个字符串。当没有非空值时,返回NULL。

在GROUP_CONCAT()函数中,可以使用ORDER BY对结果排序。

在进行拼接时,默认使用“,”作为分隔符,可以使用SEPARATOR 'xxx’指定分隔符。

GROUP_CONCAT()函数的结果会被截取为group_concat_max_len系统变量指定的长度,其默认值为1024。即默认情况下GROUP_CONCAT()函数生成的字符串长度不超过1024。

参考 https://dev.mysql.com/doc/refman/5.6/en/server-system-variables.html#sysvar_group_concat_max_len ,group_concat_max_len系统变量在32位平台最大值为4294967295,在64位平台最大值为18446744073709551615。

按照每一行包含40个字节的SHA1值,及一个分隔符计算,32位平台的最大值4294967295最多支持超过4亿行数据的SHA1值拼接。

执行以下语句,可用于查询及修改当前使用的group_concat_max_len系统变量。

select @@group_concat_max_len;SET @@SESSION.group_concat_max_len = 4294967295;

可以将concat_ws()与group_concat()函数一起使用,使用ORDER BY指定group_concat()函数拼接时的排序字段,使用SEPARATOR指定其分隔符。

以下语句及执行结果如下:

select group_concat(r.a order by b SEPARATOR ':') from
(
select concat_ws(':', 'a', '2') as a,'b2' as b
union
select concat_ws(':', 'a', '3') as a,'b3' as b
union
select concat_ws(':', 'a', '1') as a,'b1' as b
) as r;
a:1:a:2:a:3

4. 测试数据

4.1. 测试数据库表

创建以下数据库表用于测试。

CREATE TABLE test_table_concat (id varchar(20) NOT NULL,int_value int(11) NOT NULL,decimal_value decimal(18,2) NOT NULL,create_time datetime(3) NOT NULL,update_time datetime(3) NOT NULL,PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

4.2. 生成测试数据

生成以下数据用于测试。

insert into test_table_concat(id,int_value,decimal_value,create_time,update_time) value (uuid_short(), ROUND((rand() * 100) % 100), ROUND((rand() * 100) % 100, 2), now(), now());

5. 快速比较数据库表数据的SQL脚本

为了快速获取目标数据库表中的字段名拼接结果,可以从information_schema.COLUMNS查询字段名称,使用group_concat()函数拼接,示例语句如下:

以下语句及执行结果如下:

select group_concat(column_name order by ordinal_position) from information_schema.COLUMNS where TABLE_SCHEMA='testdb' and table_name='test_table_concat';
id,int_value,decimal_value,create_time,update_time

以下为快速比较数据库表数据的SQL脚本,对上述测试数据库表进行操作。

在执行以下脚本之前,需要先将group_concat_max_len系统参数设置为足够大的值,示例如下:

SET @@SESSION.group_concat_max_len = 4294967295;

以下脚本中除了计算目标数据库表的总HASH值之外,也会获取字段总长度及总行数,便于观察数据差异。

select sha1(group_concat(sha1(r1.content) order by r1.id)) as hash, sum(length(r1.content)) as sum_length, count(r1.content) as total_count
from
(
select concat_ws(':',id,int_value,decimal_value,create_time,update_time) as content, id from test_table_concat
) as r1;

执行结果示例:

| hash                                     | sum_length | total_count |
+------------------------------------------+------------+-------------+
| 2ee683441ca43c0aa41a52a757decc4f2ebc2032 |        221 |           3 |

为了便于在不同环境的数据库之间进行对比,可在SQL脚本中写入预期的总HASH值、总长度及总数量,与实际值进行比较,使比较结果更直观,示例如下:

select r2.hash,(case when r2.hash='2ee683441ca43c0aa41a52a757decc4f2ebc2032' then '相符-HASH值' else '不相符-HASH值!' end) as hash_check,
r2.sum_length,(case when r2.sum_length=221 then '相符-总长度' else '不相符-总长度!' end) as length_check,
r2.total_count,(case when r2.total_count=3 then '相符-总数量' else '不相符-总数量!' end) as count_check
from (
select sha1(group_concat(sha1(r1.content) order by r1.id)) as hash, sum(length(r1.content)) as sum_length, count(r1.content) as total_count
from
(
select concat_ws(':',id,int_value,decimal_value,create_time,update_time) as content, id from test_table_concat
) as r1
) as r2;

执行结果示例:

| hash                                     | hash_check  | sum_length | length_check | total_count | count_check |
+------------------------------------------+-------------+------------+--------------+-------------+-------------+
| 2ee683441ca43c0aa41a52a757decc4f2ebc2032 | 相符-HASH值  |        221 | 相符-总长度   |           3 | 相符-总数量  |

若比较结果不一致,可以生成每行数据的HASH值,根据主键或其他字段排序,人工检查差异数据。

如执行以下SQL语句:

select sha1(concat_ws(':',id,int_value,decimal_value,create_time,update_time)),id from test_table_concat order by id

得到以下数据,可通过人工检查差异数据:

ecfa4ba762407c2544daf0aa483ddc614a1ba7c6 98984592530210830
a3bf188f45615ff722ad70672568f924a4c95374    98984592530210831
290f3f3bdd8f856ea531f71664e23324d3d11bd4    98984592530210832

MySQL快速比较数据库表数据相关推荐

  1. MySQL快速清空大表数据(truncate table table_name;)

    MySQL快速清空大表数据 项目初次上线,进行性能测试造的数据量巨大,都是些不可用数据,但又有一些是必须保留的,很多时候需要进行系统性的清理数据或者是,将有用的数据筛选出来之后再插入到表中!保留表结构 ...

  2. mysql两个数据库表数据同步_php同步mysql两个数据库中表的数据

    分别创建两个数据库和两张表 study库-zone表 teaching库-area表 //****SQL脚本****// 1.创建teaching数据库area数据表 create database ...

  3. mysql快速删除大表数据部分数据_mysql删除大表的部分数据

    mysql删除大表的部分数据 好久没写博客.最近项目要上线.下班时间还得陪着老妈.实在没时间更新. 今天有人提了一个问题,  www.2cto.com 一个表有1亿6000万的数据,有一个自增ID.最 ...

  4. shell脚本mysql清空指定数据库表数据(排除指定库表不清空)

    #$2 为数据库用户 .$3 为数据库密码 mysql -u$2 -p$3 << EOF #切换到指定数据库 use 数据库名称# 排除指定库表不清空 select concat('tru ...

  5. 导出远程mysql数据库中的表_shell脚本实现导出远程mysql数据库表数据至本地

    bin/main.sh脚本内容 #!/bin/bash #作用:用于同步远程mysql数据库表数据至本地 #作者:丁艺博 source /etc/profile source ~/.bash_prof ...

  6. python提取数据库数据_Python如何读取MySQL数据库表数据

    本文实例为大家分享了Python读取MySQL数据库表数据的具体代码,供大家参考,具体内容如下 环境:Python 3.6 ,Window 64bit 目的:从MySQL数据库读取目标表数据,并处理 ...

  7. mysql数据库实验查询_MySQL数据库表数据的查询操作实验

    实验3.MySQL数据库表数据的查询操作实验(1) 一.实验目的 掌握SELECT 语句的基本语法格式. 掌握SELECT 语句的执行方法. 掌握SELECT 语句的 GROUP BY 和 ORDER ...

  8. 帆软报表列表_帆软报表(finereport)读取数据库表数据生成报表

    帆软报表(finereport)读取数据库表数据生成报表 发布时间:2019-01-14 16:48, 浏览次数:856 , 标签: finereport 1.首先是安装帆软报表软件,微软的傻瓜式安装 ...

  9. 把Excel表格通过MySql Workbench导入数据库表中的使用总结

    把Excel表格通过MySql Workbench导入数据库表中的使用总结 今天接到一个任务,把excel表中的数据导入到mysql数据库中,通过半个多小时的鼓捣,基本上摸清了里面的门道. 首先,准备 ...

最新文章

  1. pytorch中的transpose()
  2. 资源 | 来自独秀同学的深度网络数学笔记,还不快收藏?
  3. Vue 中的 v-if 和 v-show 修饰符
  4. Flask 报错 RuntimeError: No application found. Either work inside a view function or push an applicati
  5. 宏在使用过程余函数的区别1
  6. matlab在常微分方程的应用,MATLAB在常微分方程上应用.ppt
  7. Ubuntu16.04 设置环境变量的方法
  8. 王文汉:大学毕业后的5-10年最重要
  9. 车道线检测综述及近期新工作
  10. 黎活明给程序员的忠告 (必藏经典)
  11. 基于php的村镇干部绩效考核系统
  12. 悉尼大学计算机专业新生,2020年悉尼大学计算机科学专业课程设置难不难
  13. C++ 动态申请二维数组与二维数组传参
  14. ORA-12505, TNS:listener does not currently know of SID given in connect descript 错误 更改方法
  15. 关于运算放大器电流流向的问题
  16. 二级干线熔接机选什么好?TFN FT-3 二级干线专用光纤熔接机
  17. 用苹果电脑开发Android应用,MAC OS Android Studio环境安装
  18. 值得珍藏的免费观影网站
  19. 64位32位 java 浏览器_Java编程语言下 Selenium 驱动各个浏览器代码
  20. 毕业设计之外文翻译(工具篇)

热门文章

  1. c语言1009 说反话 20,1009. 说反话,1009.反话
  2. 无线局域网(WLAN)系统中身份认证中ikey1000的具体应用
  3. IDA pro简单入门使用
  4. html reset 无效,HTML 5复位(html5reset.org) - X-UA兼容不起作用(Html 5 Rese
  5. gdb断点commands高级功能
  6. Tsai手眼标定算法
  7. 90 后技术宅研发 Magi 一夜爆红,新一代知识化结构搜索新时代来了?
  8. CF 1642 E. Anonymity Is Important 线段树 + 离线
  9. 小程序token过期后, 实现无感知的刷新token
  10. 面试谈薪,怎样才能谈个好薪资