V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
tusj
V2EX  ›  问与答

有人用 mysqldiff 吗?只能说勉强能用吧,有没有更好的工具?

  •  
  •   tusj · 2016-05-27 00:41:21 +08:00 · 3706 次点击
    这是一个创建于 2883 天前的主题,其中的信息可能已经有所发展或是发生改变。

    工作上经常需要对比不同环境数据库表结构差异。 用 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:root@localhost: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.
    
    real	0m0.936s
    user	0m0.404s
    sys	0m0.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 次数据拷贝,就等着哭吧!

    1 条回复    2016-05-27 18:40:38 +08:00
    tusj
        1
    tusj  
    OP
       2016-05-27 18:40:38 +08:00 via Smartisan T1
    一个回复都没有
    看来只得另想办法了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3455 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 11:14 · PVG 19:14 · LAX 04:14 · JFK 07:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.