【问题标题】:MySQL: Dump a database from a SQL queryMySQL:从 SQL 查询中转储数据库
【发布时间】:2010-01-08 00:19:55
【问题描述】:

我正在编写一个测试框架,我需要在其中捕获 MySQL 数据库状态(表结构、内容等)。

我需要这个来检查在某些操作后状态没有改变。 (自动增量值可能可以改变,但我想我可以处理这个。)

转储最好采用人类可读的格式(最好是 SQL 代码,如 mysqldump 那样)。

我希望将我的测试框架限制为仅使用 MySQL 连接。要捕获状态,它应该调用 mysqldump 或访问文件系统(如复制 *.frm 文件或执行 SELECT INTO 文件,但管道很好)。

由于这将是仅测试代码,因此我不关心性能。不过,我确实需要可靠的行为。

实现我需要的功能的最佳方式是什么?

我想我的代码应该基于一些现有的开源备份工具...哪个是最好看的?

更新:我没有指定我写这个的语言(不,那不是 PHP),因为我认为我不能按原样重用代码 - 我的情况是相当特殊(出于实际目的,让我们假设 MySQL C API)。代码将在 Linux 上运行。

【问题讨论】:

  • 什么语言?框架?平台?
  • 它不应该访问文件系统。这太模棱两可和宽泛了,你真的,真的无法绕过它。我想你的意思可能是它不应该使用任何命令行命令,这是真的吗?
  • 我更新了关于语言和文件系统的问题。

标签: mysql dump


【解决方案1】:

鉴于您的要求,我认为您只剩下(伪代码 + SQL)

tables = mysql_fetch "SHOW TABLES"
foreach table in tables
    create = mysql_fetch "SHOW CREATE TABLE table"
    print create
    rows = mysql_fetch "SELECT * FROM table"
    foreach row in rows
        // or could use VALUES (v1, v2, ...), (v1, v2, ...), .... syntax (maybe preferable for smaller tables)
        insert = "INSERT (fiedl1, field2, field2, etc) VALUES (value1, value2, value3, etc)"
        print insert

基本上,获取所有表的列表,然后遍历每个表并为每一行手动生成INSERT语句(大多数api都有一个简单的方法来获取列名列表,否则你可以回退到调用@ 987654323@)。

SHOW CREATE TABLE 已经为您完成了,但我相当肯定没有什么可以与 SHOW INSERT ROWS 类似。

当然,你可以用它做任何你想做的事情,而不是打印转储。

【讨论】:

  • 您不会错过表中的任何数据,因为SHOW CREATE TABLE 包括所有列、索引、约束、上次自动增量等。但是,我没有费心拉下任何元数据,例如视图、用户、授权等。如果这些信息对您很重要,则有 SHOW VIEWSSHOW GRANTS 或从 mysql 数据库中拉下表格。
【解决方案2】:

如果您不想使用命令行工具,换句话说,您想完全在 php 或您使用的任何语言中完成它,那么为什么不使用 SQL 本身迭代表。例如,要检查表结构,一种简单的技术是使用 SHOW CREATE TABLE table_name 捕获表结构的快照,存储结果,然后再次调用并比较结果。

你看过 mysqldump 的源代码吗?我相信您想要的大部分内容都会包含在其中。

直流

【讨论】:

  • 嗯,mysqldump 是 5K+ 行 GPL-ed C 代码,有很多特殊情况...bazaar.launchpad.net/~mysql/mysql-server/mysql-5.1/annotate/… 如果我想根据自己的需要调整它...我宁愿然后从命令行调用它。 (我还是想避免这种情况)
  • 如果您对命令行实用程序持开放态度,请查看出色的 maatkit maatkit.org/tools.html
  • 谢谢,但是,如果我只想使用命令行,我将使用 mysqldump 来减少外部依赖。我仍然想找到仅限 SQL 查询的解决方案。
  • 它会出现,然后您将重新编写自己的查询。但是 maatkit 有一些非常好的功能,旨在完成与您想要的类似的功能,浏览源代码应该有助于它用 PERL 编写,因此对于习惯于 c 的任何人来说,它应该相对容易阅读。特别是查看用于比较表的 mk-table-checksum。
【解决方案3】:

除非您自己构建导出,否则我认为没有简单的解决方案来导出和验证数据。如果您按表进行操作,LOAD DATA INFILESELECT ... INTO OUTFILE 可能会有所帮助。

我发现为每次测试重建数据库更容易。至少,我可以知道数据的确切状态。当然,运行这些测试需要更多时间,但这是一个很好的激励,可以抽象出操作并编写更少的依赖于数据库的测试。

我在一些设计不允许如此好的划分的项目中使用的另一种替代方法,使用 InnoDB 或其他一些事务数据库引擎效果很好。只要您跟踪您的事务,或在测试期间禁用它们,您就可以简单地在 setUp() 中启动事务并在 tearDown() 中回滚。

【讨论】:

  • 谢谢,我不想使用 INFILE 和 OUTFILE,因为我不想(明确地)从我的框架代码中接触文件系统。
  • 至于重建数据库——是的,我也在这样做。问题是我必须测试一个自定义的“回滚”逻辑(与 SQL 事务无关),我在其中“提交”对 DB 的多项更改,然后一个接一个地“回滚”它们,所有这些都在一个单一的测试。
猜你喜欢
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
  • 2015-01-18
  • 2012-04-27
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 1970-01-01
相关资源
最近更新 更多