工作上经常需要对比不同环境数据库表结构差异。
用 mysqldiff 试了一下,功能基本可以满足, 但还是发现了一些问题。
速度慢
在表很少的情况下都要差不多 1 秒一张表,如果数据库中表的数量成千上万,会更慢。
生成的 DDL 很啰嗦 一点都不精简。
比如两个表是这样的:
use `test`;
DROP TABLE IF EXISTS `t1`;
CREATE TABLE `t1` (
`id` bigint(20) DEFAULT NULL,
`v1` varchar(64) DEFAULT NULL,
`v2` varchar(64) DEFAULT NULL,
`v3` varchar(64) DEFAULT NULL,
`v4` varchar(64) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `t2`;
CREATE TABLE `t2` (
`id` bigint(20) DEFAULT NULL,
`v4` varchar(64) DEFAULT NULL,
`v1` varchar(64) DEFAULT NULL,
`v2` varchar(64) DEFAULT NULL,
`v3` varchar(64) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
假设 test.t1 是正确的,需要修改 test.t2,手动写出来的 DDL 肯定都这样写,一目了然:
ALTER TABLE `test`.`t2` CHANGE COLUMN v4 v4 varchar(64) NULL AFTER v3;
但通过 mysqldiff 跑出来的结果却复杂很多:
$ time mysqldiff --server1=root:[email protected]:3306 --difftype=sql --changes-for=server2 --show-reverse test.t1:test.t2
# WARNING: Using a password on the command line interface can be insecure.
# server1 on localhost: ... connected.
# Comparing test.t1 to test.t2 [FAIL]
# Transformation for --changes-for=server2:
#
ALTER TABLE `test`.`t2`
CHANGE COLUMN v1 v1 varchar(64) NULL AFTER id,
CHANGE COLUMN v2 v2 varchar(64) NULL AFTER v1,
CHANGE COLUMN v3 v3 varchar(64) NULL AFTER v2,
CHANGE COLUMN v4 v4 varchar(64) NULL AFTER v3;
#
# Transformation for reverse changes (--changes-for=server1):
#
# ALTER TABLE `test`.`t1`
# CHANGE COLUMN v1 v1 varchar(64) NULL AFTER v4,
# CHANGE COLUMN v2 v2 varchar(64) NULL AFTER v1,
# CHANGE COLUMN v3 v3 varchar(64) NULL AFTER v2,
# CHANGE COLUMN v4 v4 varchar(64) NULL AFTER id;
#
Compare failed. One or more differences found.
real0m0.936s
user0m0.404s
sys0m0.084s
$
同理,如果将 test.t1 变更成 test.t2 也是如此,手动写脚本只需要 1 个 CHANGE 。
而 mysqldiff 需要 4 个 CHANGE 。
虽然 mysqldiff 出来的结果很啰嗦,但并不影响最终效果
所有 CHANGE 都是写在一个 DDL 语句里的,所以即使表里面有大量数据需要迁移,也是一次到位的,不会比手工写的 DDL 差,所以用还是能用。
但就是看着不爽!大量垃圾信息将重点给淹没了,感觉很傻逼。
不知道各位 V 友有没有更好的工具?
或者有啥算法能解决这个问题,以最少的挪动次数来完成 DDL ?
Navicat 我也试过了,生成的脚本不行,比 mysqldiff 糟很多, 4 个 CHANGE 他会给你写出 4 条 DDL ,简直不能再傻逼了!
ALTER TABLE `test`.`t2` CHANGE COLUMN v1 v1 varchar(64) NULL AFTER id;
ALTER TABLE `test`.`t2` CHANGE COLUMN v2 v2 varchar(64) NULL AFTER v1;
ALTER TABLE `test`.`t2` CHANGE COLUMN v3 v3 varchar(64) NULL AFTER v2;
ALTER TABLE `test`.`t2` CHANGE COLUMN v4 v4 varchar(64) NULL AFTER v3;
如果表里数据量大的话,变更的时候会发生 4 次数据拷贝,就等着哭吧!