【问题标题】:Is it a good idea to purge old Rails migration files?清除旧的 Rails 迁移文件是个好主意吗?
【发布时间】:2011-05-14 00:24:46
【问题描述】:

我已经运行一个大型 Rails 应用程序超过 2 年了,我的 ActiveRecord 迁移文件夹每天都在增长到超过 150 个文件。

有一些非常旧的模型,在应用程序中不再可用,但仍然在迁移中引用。我正在考虑删除它们。

你怎么看?您通常会从代码库中清除旧的迁移吗?

【问题讨论】:

    标签: ruby-on-rails ruby activerecord migration


    【解决方案1】:

    The Rails 4 Way 第 177 页: 塞巴斯蒂安说……

    一个鲜为人知的事实是,您可以删除旧的迁移文件(同时 仍然保留较新的)以将 db/migrate 文件夹保存到 可管理的大小。您可以将较旧的迁移移动到 db/archived_migrations 文件夹或类似的东西。一旦你做了修剪 迁移文件夹的大小,使用 rake db:reset 任务 (重新)从db/schema.rb 创建您的数据库并将种子加载到 您当前的环境。

    【讨论】:

      【解决方案2】:

      一旦我发布了主要网站版本,我会将迁移整合为一个并重新开始。一旦迁移版本号上升到 75 左右,我就觉得很脏。

      【讨论】:

      • 如何将它们合二为一?手动?
      • @AlisonR。 - 当你问的时候不确定这是不是真的,但在 Rails 3 中你可以复制schema.rb
      • 为什么要把它们合二为一? schema.rb 无论如何都应该是您数据库的规范来源。您可以运行 rake db:schema:load 来获取最新的架构,然后运行 ​​rake db:migrate 来获取最新的迁移。
      【解决方案3】:

      它们相对较小,所以我会选择保留它们,仅作记录。

      您应该在不参考模型或应用程序的其他部分的情况下编写迁移,因为它们会回到您身边;)

      查看以下指南:

      http://guides.rubyonrails.org/migrations.html#using-models-in-your-migrations

      【讨论】:

      • 我尝试在没有模型引用的情况下编写迁移有一段时间了,结果发现这是一个非常令人头疼的问题,尤其是当我试图添加新的数据库约束时。我必须编写一个 rake 任务来首先清理数据,然后再推送一个迁移以添加约束,因为当存在尚未运行的迁移时,您无法运行 rake 任务。将其全部放入迁移中要容易得多。额外的好处是它是隐式事务性的,所以失败会回滚。
      • @lobati:我不明白在迁移中使用模型和新的数据库约束之间的联系。我到处使用真正的 FK、CHECK、触发器……并在迁移中使用 SQL 管理它们,我的迁移中不需要模型。
      • @muistooshort 我发现在添加约束或移动数据时能够依赖模型级别的验证和查询便利非常好。例如,当我们添加一个 FK 约束时,我们有时会发现关联的记录丢失了,因此我们可能希望以某种方式有条件地重构它或者只是销毁它。其中大部分可能可以使用原始 SQL 处理,但我也发现有额外的抽象层很好,以防我粗手指查询。
      • @lobati:我倾向于将数据库视为一个完全独立的应用程序,其 API 是 SQL。这使得数据库对其一致性负责,并且所有模型验证都是备份(用于一致性和完整性),这使得与外界的错误交流变得更容易一些。这会导致一些重复的工作,但这实际上是一个功能。就胖手指而言,这就是为什么您将约束放在数据库中的原因。损坏的代码是暂时的,损坏的数据是永远的。无论如何,我们可能在谈论同样的事情。
      • @muistooshort 我想我同意所有这些。不幸的是,我在这些事情上并不总是那么明智,而且我经常会根据我不断变化的理念或其他人的现有代码库和数据库来更新我的旧工作。旁注:如果 Rails 能够从您的数据库约束中推断验证,它可能会很方便。
      【解决方案4】:

      我个人喜欢在迁移文件中保持整洁。我认为,一旦您将所有更改都推送到 prod 中,您应该真正考虑归档迁移。我遇到的唯一困难是,当 Travis 运行时,它运行 db:migrate,所以这些是我使用的步骤:

      1. 将历史迁移从 /db/migrate/ 移动到 /db/archive/release-x.y/

      2. 使用上次在 /db/archive/release-x.y 目录中运行迁移的版本号手动创建一个新的迁移文件,并将描述更改为类似于 from_previous_version 的内容。使用旧版本号意味着它不会在您的 prod 机器上运行并搞砸。

      3. ActiveRecord::Schema.define(version: 20141010044951) do 部分复制schema.rb 内容并粘贴到from_previous_version 更改日志的change 方法中

      4. 检查所有这些,罗伯特应该是你父母的兄弟。

      唯一的其他考虑因素是您的迁移是否会创建任何数据(我的测试场景包含它们自己的所有数据,所以我没有这个问题)

      【讨论】:

      【解决方案5】:

      我偶尔会清除所有已在生产中应用的迁移,我看到至少有两个原因:

      1. 更易于管理的文件夹。如果添加了一些新的迁移,则更容易发现。
      2. 更清晰的文本搜索结果(项目中的全局文本搜索不会导致大量无用的匹配,因为旧迁移,例如,当某人在 3 年前创建了某个列时)。

      【讨论】:

        【解决方案6】:

        为什么?除非磁盘空间存在某种问题,否则我认为没有充分的理由删除它们。我想如果你绝对确定你永远不会再回滚任何东西,那么你可以。但是,为此节省几 KB 的磁盘空间似乎是不值得的。此外,如果您只想删除引用旧模型的迁移,则必须手动查看它们以确保不会删除应用程序中仍在使用的任何内容。对我来说,付出很多努力却没有收获。

        【讨论】:

        • 主要原因是/models文件夹中没有指向表的模型定义,因为模型已经被完全删除了。
        • 进行创建然后删除表的迁移可能看起来效率低下,除非进行完整的数据库构建是一个时间关键的过程,否则没有理由搞乱它们。他们喜欢闲逛。
        • 如果你真的有很多迁移,这确实很有意义,我们已经有大约 1000 个,现在运行“rake db:migrate”需要很多时间——即使有运行一次迁移,因为(我认为)Rails 首先将它们全部加载(解析)到内存中。我们还没有清除迁移,但现在我在这里 - 我一定会考虑。
        • 一个原因:我刚刚从应用程序中删除了设计(移动到单点登录)。它最初的迁移使用了t.recoverable 之类的东西,如果没有 gem,它就不存在,所以我根本无法再运行该迁移。至少我得把它注释掉。
        【解决方案7】:

        http://edgeguides.rubyonrails.org/active_record_migrations.html#schema-dumping-and-you

        迁移不是数据库的表示:structure.sql 或 schema.rb 都是。迁移也不是设置/初始化数据的好地方。 db/seeds 或 rake 任务更适合此类任务。

        那么什么是迁移?在我看来,它们是关于如何更改数据库模式的说明 - 向前或向后(通过回滚)。除非出现问题,否则它们应仅在以下情况下运行:

        1. 在我的本地开发机器上测试迁移本身并编写架构/结构文件。
        2. 在同事的开发人员机器上作为一种在不删除数据库的情况下更改架构的方法。
        3. 在生产机器上作为一种在不删除数据库的情况下更改架构的方法。

        一旦运行,它们应该就无关紧要了。当然会发生错误,因此您肯定希望将迁移保留几个月以防需要回滚。

        CI 环境永远不需要运行迁移。它会减慢您的 CI 环境并且容易出错(就像 Rails 指南所说的那样)。由于您的测试环境只有临时数据,您应该改用 rake db:setup,它将从 schema.rb/structure.sql 加载并完全忽略您的迁移文件。

        如果您使用源代码管理,则保留旧迁移没有任何好处;它们是源历史的一部分。如果那是您的一杯咖啡,将它们放在存档文件夹中可能是有意义的。

        综上所述,我强烈认为清除旧迁移是有意义的,原因如下:

        • 它们可能包含太旧以至于无法再运行的代码(就像您删除了模型一样)。这为其他想要运行rake db:migrate 的开发人员制造了一个陷阱。
        • 它们会减慢grep 类任务的速度,并且在一定年龄之后不再相关。

        为什么它们不相关?再次出于两个原因:历史记录存储在您的源代码管理中,而实际的数据库结构存储在 structure.sql/schema.rb 中。我的经验法则是,超过 12 个月的迁移完全无关紧要。我删除它们。如果出于某种原因我想回滚一个比这更早的迁移,我相信数据库在那段时间已经发生了足够的变化,足以保证编写一个新的迁移来执行该任务。

        那么如何你摆脱迁移?这些是我遵循的步骤:

        1. 删除迁移文件
        2. 编写一个 rake 任务以删除它们在数据库的 schema_migrations 表中的相应行。
        3. 运行rake db:migrate 重新生成结构.sql/schema.rb。
        4. 验证 structure.sql/schema.rb 中唯一更改的是与您删除的每个迁移相对应的删除行。
        5. 部署,然后在生产环境中运行步骤 2 中的 rake 任务。
        6. 确保其他开发人员在他们的机器上运行第 2 步中的 rake 任务。

        第二项是保持架构/结构准确所必需的,这也是这里唯一真正重要的事情。

        【讨论】:

          【解决方案8】:

          一旦您觉得不再需要旧迁移,就可以删除它们。迁移的目的是拥有一个用于进行和回滚数据库更改的工具。一旦做出更改并投入生产几个月,您就不太可能再次需要它们。我发现一段时间后它们只是杂乱无章的东西,会弄乱你的 repo、搜索和文件导航。

          有些人会从头开始运行迁移以重新加载他们的开发数据库,​​但这并不是他们真正想要的。您可以使用rake db:schema:load 加载最新架构,并使用rake db:seed 使用种子数据填充它。 rake db:reset 两者都为您服务。如果您的数据库扩展无法转储到 schema.rb,那么您可以使用 sql schema format for ActiveRecord 并运行 rake db:structure:load

          【讨论】:

            【解决方案9】:

            是的。我想如果您也从数据库中完全删除了任何模型和相关表,那么值得将其放入迁移中。如果迁移中的模型引用不依赖于任何其他东西,那么您可以将其删除。尽管该迁移永远不会再次运行,因为它已经运行,即使您不从现有迁移中删除它,但每当您重新迁移数据库时,它都会导致问题。

            最好从迁移中删除该引用。并在大版本发布到实时数据库之前重构/最小化迁移到一两个文件。

            【讨论】:

              【解决方案10】:

              我同意,100 多次迁移没有任何价值,历史记录一团糟,没有简单的方法可以跟踪单个表的历史记录,这会使您的文件查找变得混乱。简单的慕达国际海事组织:)

              这是一个三步指南,可将所有迁移压缩到与生产相同的架构:

              第 1 步:生产模式

              # launch rails console in production
              stream = StringIO.new
              ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream); nil
              stream.rewind
              puts stream.read
              

              这是可复制粘贴到迁移,减去明显的标题

              第 2 步:在没有在生产环境中运行的情况下进行迁移

              这很重要。使用上次迁移并更改其名称和内容。 ActiveRecord 将日期时间编号存储在它的 schema_migrations 表中,因此它知道它已经运行了什么而不是什么。重用最后一个,它会认为它已经运行了。

              例如:rename 20161202212203_this_is_the_last_migration -> 20161202212203_schema_of_20161203.rb

              并将架构放在那里。

              第 3 步:验证和故障排除

              在本地,rake db:drop、rake db:create、rake db:migrate

              验证架构是否相同。我们遇到的一个问题是架构中的 datetime "now()",这是我能找到的最佳解决方案:https://stackoverflow.com/a/40840867/252799

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2018-10-28
                • 1970-01-01
                • 2012-05-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多