Rails:更改生产数据库的最佳方式

时间:2022-09-15 20:51:16

I need to make changes to an in-use production database. Just adding a few columns. I've made the changes to the dev database with migrations. What is the best way to update the production database while preserving the existing data and not disrupting operation too much?

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

It's MYSQL and I will be needing to add data to the columns as well for already existing records. One column can have a default value (it's boolean) but the other is a timestamp and should have an arbitrary backdated value. The row counts are not huge.

它是MYSQL,我将需要向列添加数据以及已有的记录。一列可以有一个默认值(它是布尔值),但另一列是时间戳,应该有一个任意的后退值。行数并不大。

So if I use migrations how do I add data and how do I get it to just do the two (or three - I add data -latest migrations on the production db when it wasn't initially built via migrations (I believe they used the schema instead)?

因此,如果我使用迁移,我如何添加数据?如何才能实现这两个(或三个 - 我在生成数据库上添加数据时最多的迁移,而不是最初通过迁移构建的(我相信他们使用了架构而不是)?

4 个解决方案

#1


6  

It sounds like you're in a state where the production db schema doesn't exactly match what you're using in dev (although it's not totally clear). I would draw a line in the sand, and get that prod db in a better state. Essentially what you want to do is make sure that the prod db has a "schema_info" table that lists any migrations that you >don't< ever want to run in production. Then you can add migrations to your hearts content and they'll work against the production db.

听起来你处于这样一种状态:生产数据库模式与你在开发中使用的模式不完全匹配(虽然它并不完全清楚)。我会在沙子中划一条线,让那个prod db处于更好的状态。基本上你要做的是确保prod db有一个“schema_info”表,列出你 <不想在生产中运行的任何迁移。然后,您可以将迁移添加到您的内容中,它们将对生产数据库起作用。< p>

Once you've done that you can write migrations that add schema changes or add data, but one thing you need to be really careful about is that if you add data using a migration, you must define the model within the migration itself, like this:

完成后,您可以编写添加架构更改或添加数据的迁移,但您需要特别注意的一件事是,如果使用迁移添加数据,则必须在迁移本身中定义模型,如下所示:

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

The reason for this is that in the future, you might remove the model altogether, during some refactoring or other. If you don't define the user class on line "User.find_by_login..." the migration will throw an exception which is a big pain.

这样做的原因是,在将来,您可能会在某些重构或其他过程中完全删除模型。如果您没有在“User.find_by_login ...”行上定义用户类,则迁移将抛出异常,这是一个很大的痛苦。

#2


14  

I always follow this procedure:

我总是遵循这个程序:

  • Dump prod database with mysqldump command
  • 使用mysqldump命令转储prod数据库

  • Populate dev / test database with dump using mysql command
  • 使用mysql命令使用dump填充dev / test数据库

  • Run migrations in dev / test
  • 在dev / test中运行迁移

  • Check migration worked
  • 检查迁移工作

  • Dump prod database with mysqldump command (as it may have changed) keeping backup on server
  • 使用mysqldump命令转储prod数据库(因为它可能已更改)在服务器上保留备份

  • Run migrations on prod (using capristano)
  • 在prod上运行迁移(使用capristano)

  • Test migration has worked on prod
  • 测试迁移一直在推动

  • Drink beer (while watching error logs)
  • 喝啤酒(边看错误日志)

#3


4  

Is there a reason you are not using the same migrations you used in your dev environment?

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

#4


2  

Adding a column with add_column in a migration should be non-destructive: it will generate a "ALTER TABLE" statement. If you know what you're going to put into the columns once created, you can fill in the values within the migration (you may choose a less time-consuming alternative if the row counts are large).

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

Removing or altering the definition of a column is, I think, platform-dependent: some will allow deletion of a column in place, others will perform a rename-create-select-drop sequence of commands.

我认为删除或更改列的定义取决于平台:有些将允许删除列,其他将执行rename-create-select-drop命令序列。

To get more specific, we need more information: what kind of migration are you looking at, what platform are you running on, do you need to set values as part of the migration? Stuff like that would help a lot - just edit the question, which will push it back up the list.

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

#1


6  

It sounds like you're in a state where the production db schema doesn't exactly match what you're using in dev (although it's not totally clear). I would draw a line in the sand, and get that prod db in a better state. Essentially what you want to do is make sure that the prod db has a "schema_info" table that lists any migrations that you >don't< ever want to run in production. Then you can add migrations to your hearts content and they'll work against the production db.

听起来你处于这样一种状态:生产数据库模式与你在开发中使用的模式不完全匹配(虽然它并不完全清楚)。我会在沙子中划一条线,让那个prod db处于更好的状态。基本上你要做的是确保prod db有一个“schema_info”表,列出你 <不想在生产中运行的任何迁移。然后,您可以将迁移添加到您的内容中,它们将对生产数据库起作用。< p>

Once you've done that you can write migrations that add schema changes or add data, but one thing you need to be really careful about is that if you add data using a migration, you must define the model within the migration itself, like this:

完成后,您可以编写添加架构更改或添加数据的迁移,但您需要特别注意的一件事是,如果使用迁移添加数据,则必须在迁移本身中定义模型,如下所示:

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

The reason for this is that in the future, you might remove the model altogether, during some refactoring or other. If you don't define the user class on line "User.find_by_login..." the migration will throw an exception which is a big pain.

这样做的原因是,在将来,您可能会在某些重构或其他过程中完全删除模型。如果您没有在“User.find_by_login ...”行上定义用户类,则迁移将抛出异常,这是一个很大的痛苦。

#2


14  

I always follow this procedure:

我总是遵循这个程序:

  • Dump prod database with mysqldump command
  • 使用mysqldump命令转储prod数据库

  • Populate dev / test database with dump using mysql command
  • 使用mysql命令使用dump填充dev / test数据库

  • Run migrations in dev / test
  • 在dev / test中运行迁移

  • Check migration worked
  • 检查迁移工作

  • Dump prod database with mysqldump command (as it may have changed) keeping backup on server
  • 使用mysqldump命令转储prod数据库(因为它可能已更改)在服务器上保留备份

  • Run migrations on prod (using capristano)
  • 在prod上运行迁移(使用capristano)

  • Test migration has worked on prod
  • 测试迁移一直在推动

  • Drink beer (while watching error logs)
  • 喝啤酒(边看错误日志)

#3


4  

Is there a reason you are not using the same migrations you used in your dev environment?

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

#4


2  

Adding a column with add_column in a migration should be non-destructive: it will generate a "ALTER TABLE" statement. If you know what you're going to put into the columns once created, you can fill in the values within the migration (you may choose a less time-consuming alternative if the row counts are large).

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

Removing or altering the definition of a column is, I think, platform-dependent: some will allow deletion of a column in place, others will perform a rename-create-select-drop sequence of commands.

我认为删除或更改列的定义取决于平台:有些将允许删除列,其他将执行rename-create-select-drop命令序列。

To get more specific, we need more information: what kind of migration are you looking at, what platform are you running on, do you need to set values as part of the migration? Stuff like that would help a lot - just edit the question, which will push it back up the list.

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