为什么Rake会抛出这个Rails迁移错误?

4
我有两台机器...一台是开发机器,另一台是生产机器。当我第一次将我的rails应用程序放到生产服务器上时,没有问题。我只需通过运行rake db:schema:load RAILS_ENV=production导入schema.rb即可。一切都很好。
然后,在我的开发机器上进行了更多的更改和另一个迁移,然后将新的应用程序复制到生产机器上。然后我尝试通过运行rake db:migrate RAILS_ENV=production来更新数据库。我收到以下错误消息:"数据库中已经存在名为'schema_migrations'的对象。"
我想,你不是在开玩笑吧Rake...你创建了它!我对rake进行了跟踪,似乎rake认为这是它第一次运行。然而,通过分析我的开发机器和生产机器上的'schema_migrations'表,可以看出存在一个迁移的差异,即我要迁移的那个迁移。
我还尝试显式定义版本号,但也不起作用。
你有什么想法可以使我的生产服务器保持最新状态吗?
更新:
首先,让我说一声,我不能只是“删除”数据库。这是一个已经有超过10万条记录的生产服务器。如果将来出现类似的问题会发生什么?我每次遇到数据库问题都要删除表格吗?这次可能行得通,但这似乎不是每个数据库问题的实际长期解决方案。我怀疑我现在遇到的问题并不是唯一的。
以下是我的三点建议:
1.听起来'schema_info'表和'schema_migrations'表是相同的。在我的设置中,我只有'schema_migrations'。如前所述,在生产服务器上和开发机器上的'schema_migrations'表之间的差异仅为一个记录。也就是说,它包含我要迁移的版本号。 2.从我阅读的书《Simply Rails 2》中可以看出,当第一次转移到生产服务器时,应该运行rake db:schema:load而不是运行rake db:migrate。 3.如果有关系的话,我使用的Rails版本是2.1。
9个回答

1

根据所使用的生产系统,我见过以下情况不起作用

rake db:migrate RAILS_ENV=production

但是这个确实有效:

RAILS_ENV=production rake db:migrate

可能有些奇怪,但尝试一下看看是否会有所改变是值得的。


1
这只是我的猜测:我认为因为您在生产环境中首先运行了db:schema:load而不是db:migrate,所以您得到了数据库的结构,但没有迁移填充到schema_info表中的数据。因此,当您在生产环境中运行迁移时,schema_info中没有数据,这就是为什么迁移认为它还没有运行(因为它确实没有运行)。
话虽如此...您说您已经查看了"schema_migrations"表,并且从开发到生产有一个版本的差异...我没有听说过那个表,尽管我落后于我的rails版本几个月。也许您可以尝试在生产环境中创建一个"schema_info"表,其中包含一个"version"列,并添加一个包含您认为生产环境所在版本的行。

是的,schema_migrations表是关键,它可能不存在或未在您的生产服务器上填充。 - Cameron Booth

1
关于您的更新:
  1. 我不明白你的生产环境的 schema_migrations 和开发环境有什么区别。这两个表中是否都有记录(应该只有一个名为“version”的列,对吧),或者在生产环境中没有任何记录?如果生产环境中的表中没有任何记录,则可以执行以下操作:

    ActiveRecord::Base.connection.execute("INSERT schema_migrations (version) VALUES(#{我所假定的生产环境版本号})")

  2. 或者,您可以尝试完全删除生产环境中的 schema_migrations 表:

    ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")

    然后重新运行 rake db:migrate RAILS_ENV=production。这将从版本1开始运行迁移,这可能不是您想要的。

  3. 或者,您可以在生产环境中启动一个 IRB 会话,执行要加载的迁移文件的“require”或“load”(我总是记不清楚哪个是哪个,或者是否重要),然后调用 MyMigrationClass.up。之后,您需要手动设置 schema_migrations 表中的版本号,因为您仍然会遇到问题,但作为快速修复类型的 hack,这将起作用。


1
如果您在使用MS SQL Server数据库时遇到"There is already an object named 'schema_migrations' in the database."错误信息,那么我猜测您正在使用MS SQLServer作为数据库吗?(因为这似乎是MS SQL Server的错误消息)
如果是的话,您使用的是哪个ActiveRecord数据库适配器?(您的database.yml文件是什么,您安装了哪些gem来访问MS SQL Server数据库?)
目前似乎Rails在生产模式下找不到schema_migrations表,因此尝试创建它,并且此创建将因数据库错误消息而失败。可能的原因是schema_migrations表名称中的大小写字符——据我所知,MS SQL Server标识符区分大小写。

是的,我正在使用 MS SQL Server。我的生产机器正在运行 Linux,我正在使用 ruby ODBC 适配器。我的 database.yml 文件如下所示:production: adapter: odbc dsn: YOUR_DB_DEFINITION_NAME username: USERNAME password: PASSWORD但是,'schema_migrations' 表名是小写的。 - JP Richardson
请使用以下命令连接到您的生产环境:script/console production并执行以下命令:ActiveRecord::Base.connection.tables.include?(ActiveRecord::Migrator.schema_migrations_table_name)如果返回值为false,请验证...tables和...schema_migrations_table_name的内容。 - Raimonds Simanovskis

0

我会先删除数据库,再重新添加并运行rake rb:migrate。Brad说得对,当你运行schema load时,它没有将任何记录放入schema_migrations表中。

如果在生产服务器上有不能丢失的数据,这就更加复杂了。你可以获取rake备份任务(不确定是否是核心部分),然后在生产数据库上运行rake db:backup:write,然后在将迁移更新到生产环境后,运行rake db:backup:read。


如果这是真的,或者是最佳路径,那么生产系统就永远不会进行任何更改,而在现实生活中,几乎总是需要维护数据的 :) - Ian Terrell
我之所以推荐它,是因为他第一次没有正确运行迁移。 - Kyle Boon

0

schema_info是旧版本的Rails。而schema_migrations则是新一代的关键字。你应该可以移除schema_info表格,因为它将不再被使用。你可能希望搜索与这个名称更改相关的任何问题。


0

rake db:schema:load 会从 schema.rb 文件中加载数据库结构。该文件是数据库结构的当前表示形式。当您有一个空的模式(数据库)需要创建所有表和索引时,它会被使用。这样可以避免运行所有迁移。如果您有一个已经存在数据的生产数据库,您不想运行它。正如其他人所说,那将是不好的!


0

我知道这篇文章是一段时间之前的,但我偶然发现它并没有得到真正的回答。既然它在谷歌上出现了,那就让我来回答吧。

当你运行 rake db:schema:dump(或者当构建脚本为你执行此操作时),它会将迁移表的定义放入 schema.rb 中。在脚本的末尾,该过程将尝试再次创建表,但显然它已经存在了。在运行 rake:schema:load 之前,只需从 schema.rb 中删除迁移表即可,这样就不会出现错误消息。

您需要在迁移表中设置版本号以随后运行迁移。因此,重要的是要知道您的 schema.rb 对应的版本号,或者删除所有旧的迁移(它们安全地保存在您的 SCM 中,对吧?)


-1
rake db:migrate RAILS_ENV=production

只有在第一次创建时才使用db:schema:load任务,增量更改应该进行迁移。


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