我想问是否可以比较两个巨大数据库的完整数据库结构。 我们有两个数据库,一个是开发数据库,另一个是生产数据库。 有时我会忘记在发布部分代码之前对生产数据库进行更改,这会导致生产数据库不具有相同的结构,因此如果我们发布某些内容,就会出现一些错误。 有没有办法比较两者,或者同步?
对于 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。
您可以使用命令行:
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
为了回答此类问题,我制作了一个脚本,使用
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
);
希望这个脚本也可以帮助那些寻找非应用程序解决方案,但使用脚本的人。干杯
您可以使用 --no-data 转储它们并比较文件。
请记住在生产数据库上使用 --lock-tables=0 选项以避免大的令人讨厌的全局锁定。
如果您使用相同的 mysqldump 版本(您的开发系统和生产系统应该具有相同的软件,对吗?),那么您将期望获得或多或少相同的文件。这些表格将按字母顺序排列,因此简单的差异将轻松显示差异。
我尝试了 mysqldiff 没有成功,所以我想通过提请注意 mysqlworkbench 的比较功能来丰富未来的读者。 http://dev.mysql.com/doc/workbench/en/wb-database-diff-report.html#c13030
如果打开模型选项卡,然后选择数据库菜单,您将获得比较模式选项,您可以使用该选项来比较两个不同服务器上的两个不同模式,或同一服务器上的两个模式,或一个模式和一个模型,或者很多其他我还没有尝试过的选择。
对于 Linux 上的 mysql,可以通过 phpmyadmin 导出不带“数据”而仅结构的数据库。
滚动浏览整个数据库的导出选项,只需取消选择“数据”并将输出设置为文本即可。导出您想要比较的两个数据库。然后在您首选的程序/站点中的文件比较中,比较数据库的两个文本文件输出。在此解决方案中,同步仍然是手动的,但这对于比较和发现结构差异是有效的。
为此我使用 Embarcadero 的 ER/Studio。它具有比较和合并功能。
还有很多其他工具,例如 Toad for MySQL,也有比较。也同意 Red-Gate 建议,但从未将其用于 MySQL。
它不比较行级数据差异,但它比较表、函数、存储过程等......而且速度快如闪电。 (新版本 1.4 在 4 秒内加载并比较 1k 存储过程,而我测试过的其他工具则需要 10 秒以上。)
每个人都是对的,RedGate 确实是很棒的工具。