【问题标题】:How to I merge two databases with same schema that are on Heroku?如何合并 Heroku 上具有相同架构的两个数据库?
【发布时间】:2010-09-29 02:00:45
【问题描述】:

我在 heroku 上创建了两个基本相同的应用程序。他们一开始是不同的,因为我正在测试上传到 heroku 并且在进行调整时遇到了一些挑战。

但现在看来一切正常,但两者都有我想要整合的数据。由于它们运行相同的 git 存储库,因此代码是相同的,迁移也是。

似乎我需要在本地将其关闭并合并,但不完全清楚如何做到这一点。在 Google 上进行了一些搜索,但没有得到明确的结果。

我想要一些关于一步一步的帮助,我没有一个明确的过程。

1) 我在拥有数据库的 heroku 上有两个应用程序。它们具有相同的架构;

2) 我不需要知道数据的来源:我只需要将所有数据都驻留在一个数据库中

3) 我希望能够使用特定的 sql 命令来执行此操作,而不是手动打开(不确定我会如何执行此操作)然后进行修改,因为大约有 10 个不同的相互关联的表。

谢谢!

【问题讨论】:

  • 整合数据后,您是否需要能够区分数据的来源?
  • 不...都是一组数据。

标签: ruby database merge heroku


【解决方案1】:

没有自动的方法来做到这一点,因为没有办法以通用的方式自动完成(不做一些你想做的事情)。因此,这需要几个步骤,但您可以一直使用工具。

您可以使用 Heroku 的内置工具来获取表的转储。首先下载数据并将其导入数据库,然后将其转储到文本文件(SQL 格式)中。

一旦您在 SQL 中将其中一个数据集作为文本,您需要稍微编辑该文件。您需要将其设为导入脚本,而不是从删除现有行(或表)开始的“重建数据库”脚本。如果您小心,它可能已经采用正确的格式,但可能会出现问题。

您可能会遇到一些问题:

  • 如果您已经为记录生成了密钥(您可能会这样做),那么您必须在要导入的数据集中重新编号。可能有一种方法可以在不生成密钥的情况下导出它们,但我所做的是使用快速 grep 将它们重新编号到我要合并到的数据库范围之外。
  • 如果在其他表中有对这些键的引用(作为外键),您也必须在那里重新编号。
  • 某些表可能是“参考表”,并且在两个系统上都相同,因此您可以跳过导入它们。
  • 有些表可能不需要合并。

一旦您的文本文件处于良好状态,就可以在本地运行它并对其进行测试。如果它搞砸了,别担心——只需下载生产数据(您要导入的数据),然后再试一次。迭代,直到您在本地一切正常。然后,将文件上传到 heroku。

我知道这听起来像几个步骤 - 确实如此。不过,没有棘手的问题需要解决。你只需要慢慢来,小心翼翼。让某人与您配对,以帮助您考虑清楚。

【讨论】:

  • 谢谢...所以 sqlite3 中的本地数据库....我不知道如何打开,它看起来只是胡言乱语。所以我不确定如何进行这种合并——没有工具存在?
  • 你可以运行 sqlite3 /path/to/database 来执行命令。
  • 我明白了...我想我正在寻找将文件实际合并在一起的特定命令,包括更改引用的键之类的一些事情?还是可以用一个简单的平面文件打开?
  • 您可能可以将每个 sqlite3 表导出为 CSV 或类似格式并合并,祝您好运
  • 不要将数据导入本地数据库,而是从您的 heroku 应用程序创建一个包并下载该包。在捆绑包(它是一个 TAR 文件)中,您会找到 SQL-Dump。见这里:docs.heroku.com/backups
【解决方案2】:

假设您不需要消除重复,您可以为每个表执行此操作

insert into db1.tablea
select * from db2.tablea ;

一些并发症:

  • 如果表有 id 列,则需要通过用新 id 替换旧 id 来确保它们不会发生冲突
  • 但是,由于 id 是链接表的键,因此您需要确保每个表中的新 id 匹配。

这是一种快速而肮脏的方法:

  • 在第一个数据库的 any 表中查找最高 id。
  • 将此称为 max_key_db1。
  • 然后将第二个数据库中的所有键更新为 current_value 加上 max_key_db1。

请注意,您需要同时更新主键和外键才能使其正常工作,例如:

update db2.tablea set id = id + max_key_db1, foreign_id = foreign_id + max_key_db1;
update db2.tableb set id = id + max_key_db1, a_id = a_id + max_key_db1;
etc.

现在您有了一个自洽的 db2,其中所有键(主键和外键)都具有 db1 中不存在的值;换句话说,您的键在两个数据库中是唯一的。

现在您可以将 db2 中的行插入到 db1 中:

insert into db1.tablea
select * from db2.tablea ;

请注意,如果插入的表使用自动增量或触发器创建自己的 id,则此将不起作用;在这种情况下,您必须明确指定 ciolumns 并关闭任何自动生成的 id:

insert into db1.tablea( id, foreign_id, col1, ...)
select id, foreign_id, col1 from db2.tablea ;

或者,您可以保持 db2 不变,只需对每个表执行此操作即可:

insert into db1.tablea( id, foreign_id, col3, col4)
select id + max_key_db1, foreign_id + max_key_db1, col3, col4 from db2.tablea ;

当然,这一切都在一个事务中完成,并且在你确定你已经得到每个表并且一切都正确之前不要提交。并在您的数据库的副本上执行此操作。

现在,由于您在 db1 中使用了最高键而不考虑表,因此您的 id 可能不会是连续的,但谁在乎呢?钥匙就是钥匙。您需要做的是为每个表重置任何 auto_increment 或序列,以便下一个自动生成的键高于该表中的最高键。如何做到这一点取决于您使用的 RDBMS。

【讨论】:

  • 抱歉问了一个菜鸟问题,但是 sqlite3 看起来像一个平面文件,我在哪里实际发出这些命令?
  • 在数据库上运行(从命令行)sqlite:sqlite3 database-name
  • 所以这是一步一步的....你建议我怎么做副本?我可能需要一步一步来,因为我不确定如何做到这一点......我已经添加了一个赏金:)
【解决方案3】:

要关闭这个——决定手动选择正确的数据并重新输入,这样我就可以进行一些错误检查——很痛苦,但这种方法似乎没有一个简单的答案。自我提醒:将所有生产数据保留在生产和试驾中。

【讨论】:

    【解决方案4】:

    如果您只需要这样做一次,您可以使用 ms access 轻松完成。

    您可以通过在可视化查询设计器中创建一些查询来解决任何冲突。

    您可以使用odbc driver for sqllite3 连接到 sqlite3 数据库并在 access 中链接这些表。

    【讨论】:

      猜你喜欢
      • 2010-10-14
      • 2013-03-24
      • 2013-09-06
      • 1970-01-01
      • 1970-01-01
      • 2014-03-30
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      相关资源
      最近更新 更多