Rails:修改生产数据库的最佳方法

11
我需要对正在使用的生产数据库进行更改,只需添加一些列。我已经通过迁移在开发数据库中进行了更改。在保留现有数据且不会过多干扰操作的情况下,更新生产数据库的最佳方法是什么?
这是MYSQL数据库,我还需要为已有记录添加数据到新添加的列中。一个列可以有一个默认值(它是布尔值),但另一个是时间戳,并应该具有任意的过去日期值。行数并不是很多。
因此,如果我使用迁移,如何添加数据,并在生产数据库上执行两个(或三个 - 我添加数据 - 最新迁移),当初它并没有通过迁移构建(我相信他们使用了架构)?
4个回答

14

我总是按照以下步骤进行操作:

  • 使用mysqldump命令转储生产数据库
  • 使用mysql命令将dump文件填充到开发/测试数据库中
  • 在开发/测试环境下运行迁移
  • 检查迁移是否成功
  • 再次使用mysqldump命令转储生产数据库(因为它可能已经发生了变化),并在服务器上保留备份
  • 使用capristano在生产环境中运行迁移
  • 测试迁移是否在生产环境中成功
  • 喝啤酒(观察错误日志)

你是在手动执行所有非Capistrano和非Beer步骤吗?看起来有很多地方可以使用老式的自动化/脚本化来简化流程。 - Ev Dolzhenko
前三个步骤已经脚本化了。检查是自动化测试和手动测试的结合体。手动测试特别关注我知道已经改变的区域。我只会每隔几周才推送到生产环境。 - RichH

6
听起来你所处的状态是生产数据库架构与开发中使用的不完全匹配(尽管不是完全清楚)。我建议您划定一个界限,使生产数据库处于更好的状态。实际上,您需要确保生产数据库具有“schema_info”表,列出您永远不想在生产中运行的任何迁移。然后,您可以添加任意数量的迁移,并且它们将针对生产数据库工作。
完成该操作后,您可以编写迁移以添加模式更改或数据,但需要特别小心的一件事情是,如果您使用迁移添加数据,则必须在迁移本身中定义模型,就像这样:
class AddSomeColumnsToUserTable < ActiveRecord::Migration
  class User < ActiveRecord::Base; end
  def self.up
    add_column :users, :super_cool, :boolean, :default => :false
    u = User.find_by_login('cameron')
    u.super_cool = true
    u.save
  end

  def self.down
    remove_column :users, :super_cool
  end
end

这是因为在未来的重构中,您可能会完全删除该模型。如果您不在“User.find_by_login…”行上定义用户类,则迁移将抛出异常,这非常麻烦。

4

你没有使用在开发环境中使用的迁移文件,这是有原因的吗?


2
数据库已经在使用中,因此我不想丢失现有数据,并且如果可以避免的话,宁愿不花时间重新构建和重新填充。 - srboisvert
那么,迁移是破坏性的吗?或者您目前正在使用迁移,但以前从未在生产环境中使用过,因此它将尝试执行所有迁移,其中一些是较旧且不再相关的,因此可能会引起问题? - Matt
你能在问题中描述一下你的迁移会带来哪些破坏性影响吗?这可能有助于更准确地解决你的问题。 - Matt
这意味着迁移从未在生产环境中运行。因此,我需要一种方法来仅运行特定的非破坏性迁移。 - srboisvert

2
在迁移中使用add_column添加列应该是非破坏性的:它将生成一个"ALTER TABLE"语句。如果您知道创建后要放入列中的内容,可以在迁移中填写这些值(如果行数很大,则可以选择一个耗时较少的替代方法)。
删除或更改列的定义可能与平台相关:有些平台允许直接删除列,而其他平台则执行重命名-创建-选择-删除序列命令。
为了更具体地了解情况,我们需要更多信息:您正在查看哪种类型的迁移,您运行在哪个平台上,您是否需要在迁移中设置值?类似这样的信息会有很大帮助 - 只需编辑问题,它就会重新出现在列表中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接