编写数据库迁移以逆向复杂迁移

Posted

技术标签:

【中文标题】编写数据库迁移以逆向复杂迁移【英文标题】:Writing database migration to reverse complex migration 【发布时间】:2013-02-08 01:07:16 【问题描述】:

我的朋友在旧版应用程序上进行了相当古老的迁移,其中包含此 sn-p:

class MakeChangesToProductionDbToMatchWhatItShouldBe < ActiveRecord::Migration
  def self.up

# For some reason ActiveRecord::Base.connection.tables.sort().each blows up
    ['adjustments',
    'accounts',
     ...## more rows of classes here ###...
    'product_types'].each do |table|
      t = table.singularize.camelize.constantize.new
      if t.attributes.include?('created_at')
        change_column( table.to_sym, :created_at, :datetime,  :null => false ) rescue puts      "#table doesnt have created_at"
      end
      if t.attributes.include?('updated_at')
        change_column( table.to_sym, :updated_at, :datetime,  :null => false ) rescue puts "#table doesnt have updated_at"
      end
    end

这个旧迁移现在与我为删除这个长列表中提到的两个表而编写的新迁移冲突,这现在导致任何部署在 rake db:migrate 时出错。

为了解决此迁移并让 db:migrate 再次工作,要编写哪种迁移或关闭操作的正确类型是什么?

【问题讨论】:

【参考方案1】:

有一些不同的最佳实践可以提供帮助,但归根结底,没有什么好的方法可以在运行时不单步执行代码库的情况下始终从任意点升级数据库迁移(说到这,为什么还没有 rake 任务来执行此操作?)。

    始终包含您正在处理的模型的迁移命名空间副本。下面的例子。 从头开始构建数据库时,不要运行迁移...使用db:schema:load,它将重新创建数据库的最后一个快照。 不要让您的迁移变得荒谬且带有攻击性的标题,例如 MakeChangesToProductionDbToMatchWhatItShouldBe。 避免在编写迁移时对它们将在其中运行的环境做出假设。这包括指定表名、数据库驱动程序、环境变量等。 只要向下操作可行,就在编写操作时记下操作。当一系列转换在您的脑海中浮现时,通常会容易得多(尤其是在深奥或复杂的迁移中)。

对于这种特定情况,有理由宣布“迁移破产”——清除部分或全部现有迁移(或重构并合并成一个新迁移)以实现所需的数据库状态。当你这样做时你不再向后兼容所以不能掉以轻心,但有时它是适当的举动。

【讨论】:

这是一个很好的整体建议,即使它不是一个直接的解决方案。接受它!谢谢!

以上是关于编写数据库迁移以逆向复杂迁移的主要内容,如果未能解决你的问题,请参考以下文章

复杂分支系统中的数据库迁移

迁移复杂的核心数据模型

在实时数据库中迁移数据的查询?

(转)如何将数据库从SQL Server迁移到MySQL

Room 中的数据库迁移

迁移项目以使用 localDB