【发布时间】:2011-05-14 00:24:46
【问题描述】:
我已经运行一个大型 Rails 应用程序超过 2 年了,我的 ActiveRecord 迁移文件夹每天都在增长到超过 150 个文件。
有一些非常旧的模型,在应用程序中不再可用,但仍然在迁移中引用。我正在考虑删除它们。
你怎么看?您通常会从代码库中清除旧的迁移吗?
【问题讨论】:
标签: ruby-on-rails ruby activerecord migration
我已经运行一个大型 Rails 应用程序超过 2 年了,我的 ActiveRecord 迁移文件夹每天都在增长到超过 150 个文件。
有一些非常旧的模型,在应用程序中不再可用,但仍然在迁移中引用。我正在考虑删除它们。
你怎么看?您通常会从代码库中清除旧的迁移吗?
【问题讨论】:
标签: ruby-on-rails ruby activerecord migration
The Rails 4 Way 第 177 页: 塞巴斯蒂安说……
一个鲜为人知的事实是,您可以删除旧的迁移文件(同时 仍然保留较新的)以将
db/migrate文件夹保存到 可管理的大小。您可以将较旧的迁移移动到db/archived_migrations文件夹或类似的东西。一旦你做了修剪 迁移文件夹的大小,使用rake db:reset任务 (重新)从db/schema.rb创建您的数据库并将种子加载到 您当前的环境。
【讨论】:
一旦我发布了主要网站版本,我会将迁移整合为一个并重新开始。一旦迁移版本号上升到 75 左右,我就觉得很脏。
【讨论】:
schema.rb。
schema.rb 无论如何都应该是您数据库的规范来源。您可以运行 rake db:schema:load 来获取最新的架构,然后运行 rake db:migrate 来获取最新的迁移。
它们相对较小,所以我会选择保留它们,仅作记录。
您应该在不参考模型或应用程序的其他部分的情况下编写迁移,因为它们会回到您身边;)
查看以下指南:
http://guides.rubyonrails.org/migrations.html#using-models-in-your-migrations
【讨论】:
我个人喜欢在迁移文件中保持整洁。我认为,一旦您将所有更改都推送到 prod 中,您应该真正考虑归档迁移。我遇到的唯一困难是,当 Travis 运行时,它运行 db:migrate,所以这些是我使用的步骤:
将历史迁移从 /db/migrate/ 移动到 /db/archive/release-x.y/
使用上次在 /db/archive/release-x.y 目录中运行迁移的版本号手动创建一个新的迁移文件,并将描述更改为类似于 from_previous_version 的内容。使用旧版本号意味着它不会在您的 prod 机器上运行并搞砸。
从ActiveRecord::Schema.define(version: 20141010044951) do 部分复制schema.rb 内容并粘贴到from_previous_version 更改日志的change 方法中
检查所有这些,罗伯特应该是你父母的兄弟。
唯一的其他考虑因素是您的迁移是否会创建任何数据(我的测试场景包含它们自己的所有数据,所以我没有这个问题)
【讨论】:
我偶尔会清除所有已在生产中应用的迁移,我看到至少有两个原因:
【讨论】:
为什么?除非磁盘空间存在某种问题,否则我认为没有充分的理由删除它们。我想如果你绝对确定你永远不会再回滚任何东西,那么你可以。但是,为此节省几 KB 的磁盘空间似乎是不值得的。此外,如果您只想删除引用旧模型的迁移,则必须手动查看它们以确保不会删除应用程序中仍在使用的任何内容。对我来说,付出很多努力却没有收获。
【讨论】:
t.recoverable 之类的东西,如果没有 gem,它就不存在,所以我根本无法再运行该迁移。至少我得把它注释掉。
见http://edgeguides.rubyonrails.org/active_record_migrations.html#schema-dumping-and-you
迁移不是数据库的表示:structure.sql 或 schema.rb 都是。迁移也不是设置/初始化数据的好地方。 db/seeds 或 rake 任务更适合此类任务。
那么什么是迁移?在我看来,它们是关于如何更改数据库模式的说明 - 向前或向后(通过回滚)。除非出现问题,否则它们应仅在以下情况下运行:
一旦运行,它们应该就无关紧要了。当然会发生错误,因此您肯定希望将迁移保留几个月以防需要回滚。
CI 环境永远不需要运行迁移。它会减慢您的 CI 环境并且容易出错(就像 Rails 指南所说的那样)。由于您的测试环境只有临时数据,您应该改用 rake db:setup,它将从 schema.rb/structure.sql 加载并完全忽略您的迁移文件。
如果您使用源代码管理,则保留旧迁移没有任何好处;它们是源历史的一部分。如果那是您的一杯咖啡,将它们放在存档文件夹中可能是有意义的。
综上所述,我强烈认为清除旧迁移是有意义的,原因如下:
rake db:migrate 的开发人员制造了一个陷阱。grep 类任务的速度,并且在一定年龄之后不再相关。为什么它们不相关?再次出于两个原因:历史记录存储在您的源代码管理中,而实际的数据库结构存储在 structure.sql/schema.rb 中。我的经验法则是,超过 12 个月的迁移完全无关紧要。我删除它们。如果出于某种原因我想回滚一个比这更早的迁移,我相信数据库在那段时间已经发生了足够的变化,足以保证编写一个新的迁移来执行该任务。
那么如何你摆脱迁移?这些是我遵循的步骤:
rake db:migrate 重新生成结构.sql/schema.rb。第二项是保持架构/结构准确所必需的,这也是这里唯一真正重要的事情。
【讨论】:
一旦您觉得不再需要旧迁移,就可以删除它们。迁移的目的是拥有一个用于进行和回滚数据库更改的工具。一旦做出更改并投入生产几个月,您就不太可能再次需要它们。我发现一段时间后它们只是杂乱无章的东西,会弄乱你的 repo、搜索和文件导航。
有些人会从头开始运行迁移以重新加载他们的开发数据库,但这并不是他们真正想要的。您可以使用rake db:schema:load 加载最新架构,并使用rake db:seed 使用种子数据填充它。 rake db:reset 两者都为您服务。如果您的数据库扩展无法转储到 schema.rb,那么您可以使用 sql schema format for ActiveRecord 并运行 rake db:structure:load。
【讨论】:
是的。我想如果您也从数据库中完全删除了任何模型和相关表,那么值得将其放入迁移中。如果迁移中的模型引用不依赖于任何其他东西,那么您可以将其删除。尽管该迁移永远不会再次运行,因为它已经运行,即使您不从现有迁移中删除它,但每当您重新迁移数据库时,它都会导致问题。
最好从迁移中删除该引用。并在大版本发布到实时数据库之前重构/最小化迁移到一两个文件。
【讨论】:
我同意,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
【讨论】: