【问题标题】:Rails: Is it bad to have an irreversible migration?Rails:进行不可逆转的迁移是不是很糟糕?
【发布时间】:2010-10-11 21:33:39
【问题描述】:

何时可以在迁移的 self.down 方法中引发 ActiveRecord::IrreversibleMigration 异常?您应该在什么时候努力实际实施迁移的逆向操作?

【问题讨论】:

    标签: ruby-on-rails migration


    【解决方案1】:

    如果您正在处理生产级系统,那么是的,这是非常糟糕的。如果这是您自己的宠物项目,那么任何事情都是允许的(如果没有别的,这将是一种学习体验 :) 尽管迟早,即使在宠物项目中,您也会发现自己已经跨越了反向迁移只是必须在几天后撤消该迁移,无论是通过rake还是手动。)

    在生产场景中,您应该始终努力编写和测试可逆迁移,以防万一在生产环境中通过它,然后发现错误这会迫使您回滚(代码 架构)到某个先前的修订版(等待一些重要的修复——以及其他无法使用的生产系统。)

    反向迁移的范围从大多数微不足道的(删除在迁移期间添加的列或表,和/或更改列类型等)到更复杂的(execute of JOINed INSERTs 或 @987654326 @s),但没有什么比“把它扫到地毯下”更复杂的了。如果不出意外,强迫自己思考实现反向迁移的方法可以让您对正向迁移正在解决的问题有新的认识。

    您可能偶尔会遇到向前迁移删除某个功能的情况,从而导致数据从数据库中被丢弃。 出于显而易见的原因,反向迁移无法恢复丢弃的数据。尽管在这种情况下,我们可以建议让正向迁移自动保存数据或在可能发生回滚时将其保留作为彻底的替代方案失败(保存到yml、复制/移动到特殊表等),您不必这样做,因为测试这种自动化过程所需的时间可能超过手动恢复数据所需的时间(如果需要出现。)但即使在这种情况下,也可以不只是失败,您总是可以使反向迁移有条件地暂时失败,等待一些用户操作(即测试是否存在一些需要手动恢复的表;如果丢失,输出“我失败了,因为我无法从虚无中重新创建表XYZ;从备份中手动恢复表XYZ,然后再次运行我,我不会让你失望! ")

    【讨论】:

    • 一旦你有几十个或几百个迁移,也值得在 up 中抛出一个异常,大意是“这是不可逆的。你确定吗?”
    • 您可以在运行迁移之前使用OffScale DataGrove 保存数据库的完整状态。如果您需要恢复迁移,即使您的迁移实际上丢弃了数据,您也可以这样做。您还可以使用它来测试迁移。
    【解决方案2】:

    如果您要破坏数据,您可以先对其进行备份。 例如

    def self.up
      # create a backup table before destroying data 
      execute %Q[create table backup_users select * from users]  
      remove_column :users, :timezone
    end  
    
    def self.down
      add_column :users, :timezone, :string  
      execute %Q[update users U left join backup_users B on (B.id=U.id) set U.timezone = B.timezone]
      execute %Q[drop table backup_users]  
    end
    

    【讨论】:

      【解决方案3】:

      在生产场景中,您应该始终努力编写和测试可逆迁移,以防万一您在生产中经历它,然后发现一个错误,迫使您回滚(代码和架构)到以前的某个修订(等待一些重要的修复 - 以及其他无法使用的生产系统。)

      进行可逆迁移对于开发和暂存来说很好,但假设代码经过良好测试,那么您想要在生产中向下迁移的情况应该是极其罕见的。我在我的迁移中构建了生产模式下的自动 IrreversibleMigration。如果我真的需要撤消更改,我可以使用另一个“向上”迁移或删除异常。不过,这似乎很粗略。任何会导致这种可怕情况的错误都表明 QA 流程被严重搞砸了。

      【讨论】:

      • 或者公司太小,没有一个好的QA流程,或者经理不支持。
      • 我们通常接受一件事作为生产和登台之间的区别:数据库的内容。因此,QA 最有可能无法捕获的事情是迁移遇到被忽视的案例。这也是最可能出错的最严重的事情之一。谨慎似乎是合理的。
      【解决方案4】:

      感觉您需要进行不可逆转的迁移,这可能表明您遇到了更大的问题。也许一些细节会有所帮助?

      至于你的第二个问题:我总是“努力”写迁移的逆向。当然,实际上并没有写.down,TextMate在创建.up时会自动插入。

      【讨论】:

        【解决方案5】:

        Reversible Data Migration 使用 yaml 文件可以轻松创建可逆的数据迁移。

        class RemoveStateFromProduct < ActiveRecord::Migration
          def self.up
            backup_data = []
            Product.all.each do |product|
              backup_data << {:id => product.id, :state => product.state}
            end
            backup backup_data
            remove_column :products, :state
          end
          def self.down
            add_column :products, :state, :string
            restore Product
          end
        end
        

        【讨论】:

          【解决方案6】:

          IIRC,在迁移中更改数据类型时,您将拥有 IrreversibleMigration。

          【讨论】:

            【解决方案7】:

            我认为另一种可以的情况是您进行合并迁移时。在这种情况下,“向下”实际上没有意义,因为它会删除所有表(合并后添加的表除外)。这可能不是你想要的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-10-06
              • 2010-11-24
              • 1970-01-01
              • 2010-10-30
              • 1970-01-01
              • 2015-10-29
              • 2011-09-20
              相关资源
              最近更新 更多