rake db:schema:load 与迁移

Posted

技术标签:

【中文标题】rake db:schema:load 与迁移【英文标题】:rake db:schema:load vs. migrations 【发布时间】:2011-08-19 19:16:12 【问题描述】:

这里有一个非常简单的问题 - 如果迁移会随着应用程序变得越来越复杂而变得缓慢和繁琐,并且如果我们可以调用更简洁的 rake db:schema:load 来代替,那么为什么还存在迁移?

如果上述问题的答案是迁移用于版本控制(对数据库的更改的逐步记录),那么随着应用程序变得更加复杂并且更多地使用rake db:schema:load,他们是否会继续维护他们的主要功能?


注意:

从这个问题的答案:rake db:schema:load 将删除生产服务器上的数据,所以使用时要小心。

【问题讨论】:

+1 我从来不明白迁移的目的;为什么不只是版本控制架构? @alternative - 迁移允许你做其他事情,比如如果你需要添加一个非空列,你可以巧妙地用数据填充该列,而不是使用一些默认值。 【参考方案1】:

所以 schema:load 采用当前配置的模式,派生要匹配的关联查询,并一次性运行它们。这是一种一劳永逸的情况。如您所见,迁移会逐步进行更改。在本地处理项目时加载模式可能有意义,尤其是在项目生命周期的早期。但是,如果我们在每次部署时都删除并重新创建生产数据库,每次都会丢失生产数据。那是不行的。这就是我们使用迁移对现有数据库进行所需更改的原因。

所以。您对项目的深入了解,当您对数据库进行更多更改时,您将获得更多的迁移。随着每次迁移,这些迁移越来越成为生产环境的真实来源——重要的不是架构中的内容,而是生产环境中运行的迁移。如果我们两者同步,那么差异实际上是没有意义的。但是,一旦一个与另一个过时,您就会开始出现差异。理想情况下这不会发生,但我们生活在现实世界中,并且事情会发生。如果您使用 schema:load 在本地设置数据库,您可能无法获得数据库的实际状态,因为它通过生产中的迁移历史反映。

【讨论】:

【参考方案2】:

迁移提供对数据库的向前和向后步进更改。在生产环境中,必须在部署期间对数据库进行增量更改:迁移为该功能提供了回滚故障保护。如果您在生产服务器上运行rake db:schema:load,您最终将删除所有生产数据。这是一个危险的习惯。

话虽如此,我认为偶尔“崩溃”迁移是一种体面的做法。这需要删除旧迁移,用单个迁移替换它们(非常类似于您的 schema.rb 文件)并更新 schema_migrations 表以反映此更改。 这样做时要非常小心!如果您不小心,您可以轻松删除您的生产数据。

附带说明,我坚信您永远不应该将数据创建放在迁移文件中。 seed.rb 文件可用于此,或自定义 rake 或部署任务。将其放入迁移文件中会使您的数据库模式规范与数据规范混合在一起,并可能在运行迁移文件时导致冲突。

【讨论】:

感谢您通知 rake db:schema:load 删除所有生产数据! 我没有用模仿模式的新迁移替换“折叠”迁移,而是编写了一个 gem 来清除它们,并提示用户在尝试运行 db:migrate 时使用 db:schema:load反对全新安装。 @clear_migrations 可能是一个显而易见的答案,但在第一次投入生产之前,您是否建议只删除所有迁移并使用 db.schema 作为第一次迁移? 注意:rake db:schema:load 对设置您的测试数据库也非常有用。【参考方案3】:

rake db:migrate 设置数据库中的表。当您运行迁移命令时,它将在 db/migrate/ 中查找任何 ruby​​ 文件并从最旧的开始执行它们。每个迁移文件名的开头都有一个时间戳

与运行尚未运行的迁移的rake db:migrate 不同,rake db:schema:loaddb/schema.rb 中已生成的架构加载到数据库中。

您可以了解更多关于rake database commands here的信息。

【讨论】:

【参考方案4】:

我已经发表了评论,但感觉最好把db/schema.rb文件的cmets放在这里:

# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.

其实我的经验是,迁移文件最好放在git而不是schema.rb文件...

【讨论】:

【参考方案5】:

Migrations 也允许您将数据添加到数据库。但 db:schema:load 只加载模式。

【讨论】:

通过迁移添加数据不是不好的做法吗?【参考方案6】:

偶然发现这篇文章,那是很久以前的事了,没有看到我期待的答案。

rake db:schema:load 非常适合您首次将系统投入生产。之后,您应该正常运行迁移。

这还有助于您随时清理迁移,因为即使您清理了迁移,架构也包含将其他机器投入生产的所有信息。

【讨论】:

所以您可以“清理”您的迁移,因为您永远不必使用它们?听起来很奇怪。 我不清楚db:schema:load 除了在整个开发周期中减少几秒钟之外还有什么好处。您是否曾经使用过一个构建时间超过 30 秒的应用程序?我目前正在开发一个应用程序,它的迁移文件中有错误,如果没有错误修复或运行db:schema:load,它永远不会向上迁移,这让我认为 schema:load 是在应用程序开发出现问题时使用的。 我要保留迁移的另一个论点是 Rails 核心团队将用户定向到instead of editing schema.rb, please use the migrations feature。因此,如果您在一个自动生成的文件上运行db:schema:load,而您没有再次自动生成的迁移,那么您实际上是在手动“编辑”架构并废弃迁移。我希望我能从 Rails 指南中得到引用,但他们没有讨论 schema:load,这让我在决定如何使用 schema:load 功能时更加沮丧。 =/ 我来到这个页面正是因为我同意这一点。我的经验是,一旦站点投入生产,使用迁移来更改它会更安全。尽管如此,db/schema.rb 开头的 cmets 恰恰相反! (我在每个项目开始时都会遇到问题,因为我忘记将 db/schema.rb 放在 .gitignore 中......) @AbePetrillo 哇,我完全错过了这个 cmets。当然不是,我的意思是如果你愿意,你可以清理所有生产机器上运行的 old 迁移。多年来,我一直保留它们,但我的“随时帮助您清理迁移”声明并不意味着“我永远不必使用迁移”。因此,当您部署新机器时,运行 rake db:schema:load 而不是 rake db:migrate。然后从那里,你可以rake db:migrate【参考方案7】:

作为其他 ORM 的用户,Rails 没有“同步和更新”功能对我来说总是很奇怪。即,通过使用模式文件(代表完整的、最新的模式),遍历现有的数据库结构并根据需要添加/删除表、列、索引。

对我来说,这会更加健壮,即使可能会慢一点。

【讨论】:

将包含数据的数据库从一个复杂的模式迁移到另一个的任务有时并非易事。它可能无法自动解决,并且数据可能无法通过单个步骤一致地迁移。 Rails 迁移是主要的,而模式是依赖的。每次迁移都会自动重新创建架构,但反之亦然。 Rails 自己的指南明确指出 schema 是 master,而不是迁移。【参考方案8】:

因为迁移可以回滚,并提供额外的功能。例如,如果您需要修改一些数据作为架构更改的一部分,那么您需要将其作为迁移来执行。

【讨论】:

以上是关于rake db:schema:load 与迁移的主要内容,如果未能解决你的问题,请参考以下文章

rake db:migrate db:reset 和 db:schema:load 之间的区别

运行 rake db:schema:load 时出现“致命:角色“root”不存在”

Rake 不会回滚迁移,参数数量错误(1 代表 0)

rake db:如果没有版本,迁移不能正常工作

markdown RAKE DB迁移命令

使用迁移进行Rake部署