【问题标题】:Compare structures of two databases?比较两个数据库的结构?
【发布时间】:2010-03-05 19:39:37
【问题描述】:

我想问是否可以比较两个庞大的数据库的完整数据库结构。 我们有两个数据库,一个是开发数据库,​​另一个是生产数据库。 在我们发布部分代码之前,我有时会忘记对生产数据库进行更改,这导致生产数据库没有相同的结构,所以如果我们发布一些东西,就会出现一些错误。 有没有办法比较两者,或者同步?

【问题讨论】:

  • 我尝试了以下所有工具,大多数需要付费,有些无法在mysql服务器上运行,而mysqldiff根本无法运行。我以转储数据库结构和命令行差异结束。这很奇怪,因为我认为它应该是一个简单的工具(比命令行 diff 更强大一点)?

标签: mysql database compare structure mysqldump


【解决方案1】:

对于 MySQL 数据库,您可以使用此查询比较视图和表(列名和列类型):

SET @firstDatabaseName = '[first database name]';
SET @secondDatabaseName = '[second database name]';

SELECT * FROM  
  (SELECT
      CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
    FROM information_schema.columns cl,  information_schema.TABLES ss
    WHERE
      cl.TABLE_NAME = ss.TABLE_NAME AND
      cl.TABLE_SCHEMA = @firstDatabaseName AND
      ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
    ORDER BY
      cl.table_name ) AS t1
LEFT JOIN                     
  (SELECT
      CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
    FROM information_schema.columns cl,  information_schema.TABLES ss
    WHERE
      cl.TABLE_NAME = ss.TABLE_NAME AND
      cl.TABLE_SCHEMA = @secondDatabaseName AND
      ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
    ORDER BY
      cl.table_name ) AS t2 ON t1.tableRowType = t2.tableRowType
WHERE 
  t2.tableRowType IS NULL        
UNION 
SELECT * FROM  
  (SELECT
      CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
    FROM information_schema.columns cl,  information_schema.TABLES ss
    WHERE
      cl.TABLE_NAME = ss.TABLE_NAME AND
      cl.TABLE_SCHEMA = @firstDatabaseName AND
      ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
    ORDER BY
      cl.table_name ) AS t1
RIGHT JOIN                     
  (SELECT
      CONCAT(cl.TABLE_NAME, ' [', cl.COLUMN_NAME, ', ', cl.COLUMN_TYPE, ']') tableRowType
    FROM information_schema.columns cl,  information_schema.TABLES ss
    WHERE
      cl.TABLE_NAME = ss.TABLE_NAME AND
      cl.TABLE_SCHEMA = @secondDatabaseName AND
      ss.TABLE_TYPE IN('BASE TABLE', 'VIEW')
    ORDER BY
      cl.table_name ) AS t2 ON t1.tableRowType = t2.tableRowType
WHERE 
  t1.tableRowType IS NULL;

如果您更喜欢使用带有 UI 的工具,您也可以使用此脚本 https://github.com/dlevsha/compalex 可以比较表、视图、键等。

Compalex 是一个用于比较两个数据库模式的轻量级脚本。它 支持 MySQL、MS SQL Server 和 PostgreSQL。

屏幕截图(比较表格)

【讨论】:

  • 这很棒。我用这个。谢谢。
  • Compalex 很棒 (+1),但不显示索引。它还显示但不强调引擎(MyISAM 与 InnoDB)的差异。
【解决方案2】:

你可以使用命令行:

mysqldump --skip-comments --skip-extended-insert -d --no-data -u root -p dbName1>file1.sql
mysqldump --skip-comments --skip-extended-insert -d --no-data -u root -p dbName2>file2.sql
diff file1.sql file2.sql

【讨论】:

  • 好主意 Gere,使用 diff 命令很容易找到差异但找不到表名,所以我跳入了 tkdiff 包。我强烈推荐它。
  • 如何跳过自增?
  • @ArunGowda 可能会添加一个正则表达式,如 | sed 's/AUTO_INCREMENT=[0-9]*//g'(在 dbName 之后)
  • @suarsenegger 为什么 diff 不显示表名的差异?
【解决方案3】:

目前为了回答这类问题,我制作了一个脚本,使用information_schema 内容来比较列、数据类型和表格

SET @database_current = '<production>';
SET @database_dev = '<development>';
-- column and datatype comparison
SELECT a.TABLE_NAME, a.COLUMN_NAME, a.DATA_TYPE, a.CHARACTER_MAXIMUM_LENGTH,
    b.COLUMN_NAME, b.DATA_TYPE, b.CHARACTER_MAXIMUM_LENGTH
FROM information_schema.COLUMNS a
    LEFT JOIN information_schema.COLUMNS b ON b.COLUMN_NAME = a.COLUMN_NAME
        AND b.TABLE_NAME = a.TABLE_NAME
        AND b.TABLE_SCHEMA = @database_current
WHERE a.TABLE_SCHEMA = @database_dev
    AND (
        b.COLUMN_NAME IS NULL
        OR b.COLUMN_NAME != a.COLUMN_NAME
        OR b.DATA_TYPE != a.DATA_TYPE
        OR b.CHARACTER_MAXIMUM_LENGTH != a.CHARACTER_MAXIMUM_LENGTH
    );
-- table comparison    
SELECT a.TABLE_SCHEMA, a.TABLE_NAME, b.TABLE_NAME
FROM information_schema.TABLES a
    LEFT JOIN information_schema.TABLES b ON b.TABLE_NAME = a.TABLE_NAME
        AND b.TABLE_SCHEMA = @database_current
WHERE a.TABLE_SCHEMA = @database_dev
    AND (
        b.TABLE_NAME IS NULL
        OR b.TABLE_NAME != a.TABLE_NAME
    );

希望这个脚本也可以帮助那些寻找非应用解决方案,而是使用脚本的人。干杯

【讨论】:

  • 我喜欢你使用 mysql-only 解决方案的想法。但是,过滤器 OR b.COLUMN_NAME != a.COLUMN_NAME 是多余的,因为在 JOIN 条件中假定等价,类似地 OR b.TABLE_NAME != a.TABLE_NAME。
  • @PaulCampbell 好点!感谢您的帮助,非常感谢。干杯
【解决方案4】:

您可以使用 --no-data 转储它们并比较文件。

记得在您的生产数据库上使用 --lock-tables=0 选项以避免大的讨厌的全局锁。

如果您使用相同的 mysqldump 版本(您的开发系统和生产系统应该具有相同的软件,对吗?)那么您会期望得到或多或少相同的文件。表格将按 alpha 顺序排列,因此简单的差异很容易显示差异。

【讨论】:

    【解决方案5】:

    对于 Linux 上的 mysql,可以通过 phpmyadmin 导出没有“数据”且只有结构的数据库。

    滚动浏览整个数据库的导出选项,只需取消选择“数据”并将输出设置为文本。导出您要比较的两个数据库。

    然后在您首选程序/站点的文件比较中,比较数据库的两个文本文件输出。在这个解决方案中,同步仍然是手动的,但这对于比较和发现结构差异是有效的。

    【讨论】:

    • 对于我需要的非常简单的比较,这是一种低开销且快速的方法。谢谢!
    【解决方案6】:

    根据您的数据库,可用的工具会有所不同。

    为此,我使用 Embarcadero 的 ER/Studio。它具有比较和合并功能。

    还有很多其他的,例如 Toad for MySQL,也有比较。也同意 Red-Gate 的建议,但从未将其用于 MySQL。

    【讨论】:

      【解决方案7】:

      查看 Gemini Delta - .NET 的 SQL 差异管理器。免费测试版可供下载,但完整版距离公开发布只有几天时间。

      它不比较行级数据差异,但它比较表、函数、存储过程等......而且速度非常快。 (新版本 1.4 加载和比较 1k Sprocs 不到 4 秒,而我测试过的其他工具需要 10 多秒。)

      虽然每个人都是对的,但 RedGate 确实是很棒的工具。

      【讨论】:

        【解决方案8】:

        我尝试了mysqldiff但没有成功,所以我想通过关注mysqlworkbench的比较功能来丰富未来的读者。 http://dev.mysql.com/doc/workbench/en/wb-database-diff-report.html#c13030

        如果您打开一个模型选项卡,然后选择数据库菜单,您将获得一个比较架构选项,您可以使用它来比较两个不同服务器上的两个不同架构,或者同一服务器上的两个架构,或者一个架构和一个模型,或者我还没有尝试过的许多其他选项。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-28
          • 1970-01-01
          • 2011-02-15
          • 1970-01-01
          相关资源
          最近更新 更多