11

我需要对正在使用的生产数据库进行更改。只需添加几列。我已经通过迁移对开发数据库进行了更改。更新生产数据库同时保留现有数据且不会过多中断操作的最佳方法是什么?

它是 MYSQL,我还需要将数据添加到列以及已经存在的记录。一列可以有一个默认值(它是布尔值),但另一列是时间戳,应该有一个任意的回溯值。行数不是很大。

因此,如果我使用迁移,我如何添加数据以及如何让它只做两个(或三个 - 我在生产数据库上添加数据 - 最新迁移,而它最初不是通过迁移构建的(我相信他们使用了模式代替)?

4

4 回答 4

14

我总是遵循这个程序:

  • 使用 mysqldump 命令转储 prod 数据库
  • 使用 mysql 命令使用转储填充开发/测试数据库
  • 在开发/测试中运行迁移
  • 检查迁移工作
  • 使用 mysqldump 命令转储 prod 数据库(因为它可能已更改)在服务器上保留备份
  • 在 prod 上运行迁移(使用 capristano)
  • 测试迁移已在 prod 上工作
  • 喝啤酒(一边看错误日志)
于 2008-10-16T05:19:59.223 回答
6

听起来您处于生产数据库架构与您在 dev 中使用的架构不完全匹配的状态(尽管尚不完全清楚)。我会在沙子上画一条线,让 prod db 处于更好的状态。本质上,您要做的是确保 prod db 有一个“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...”行定义用户类,则迁移将引发异常,这是一个很大的痛苦。

于 2008-11-07T16:47:19.223 回答
4

您是否有理由不使用您在开发环境中使用的相同迁移?

于 2008-10-15T18:14:34.153 回答
2

在迁移中添加一个列add_column应该是非破坏性的:它将生成一个“ALTER TABLE”语句。如果您知道创建后要放入列中的内容,则可以填写迁移中的值(如果行数很大,您可以选择耗时较少的替代方案)。

我认为删除或更改列的定义取决于平台:有些将允许就地删除列,有些将执行重命名-创建-选择-删除命令序列。

为了更具体,我们需要更多信息:您正在查看哪种迁移,您在哪个平台上运行,您是否需要在迁移过程中设置值?这样的东西会有很大帮助 - 只需编辑问题,这会将其推回到列表中。

于 2008-10-15T20:32:35.653 回答