改变表格时遇到僵局

时间:2012-04-26 09:53:27

标签: ruby-on-rails postgresql migration

我在包含大量行的表的Rails应用程序中运行以下迁移:

rake db:migrate
*** [] rake aborted!
*** [] An error has occurred, this and all later migrations canceled:
*** [] 
*** [] PG::Error: ERROR:  deadlock detected
*** [] DETAIL:  Process 33319 waits for AccessExclusiveLock on relation 18486 of database 16948; blocked by process 29772.
*** [] Process 29772 waits for ShareLock on transaction 8652; blocked by process 33319.
*** [] HINT:  See server log for query details.
*** [] : ALTER TABLE "topics" DROP "most_recent_post_id"
*** [] 
*** [] Tasks: TOP => db:migrate
*** [] (See full trace by running task with --trace)
 ** [] ==  RemoveMostRecentPostsColumnsOnTopics: migrating 
 ** [] Updated 56875150 rows out of 568715 tries
 ** [] -- remove_column(:topics, :most_recent_post_id)

运行的代码是:

def self.up
  rows_updated = 0
  rows_tried = 0

  Topic.find(:all).each do |topic|
    rows_tried += 1
    rows_updated += 1 if topic.update_attribute :updated_at, topic.most_recent_post_created_at
  end

  puts "Updated #{rows_updated} rows out of #{rows_tried} tries"

  remove_column :topics, :most_recent_post_id
  remove_column :topics, :most_recent_post_created_at
end

然后我尝试将其作为显式锁,但在搜索有关问题的信息时,我意识到ALTER TABLE已经使用ACCESS EXCLUSIVE锁锁定表,根据:http://www.postgresql.org/docs/9.1/static/explicit-locking.html

我可以采取哪些措施来完成更改吗?

1 个答案:

答案 0 :(得分:4)

您有两个进程尝试获得独占访问权限:

Process 33319 waits for AccessExclusiveLock on relation 18486 of database 16948; blocked by process 29772.
Process 29772 waits for ShareLock on transaction 8652; blocked by process 33319.

其中一个是您的迁移任务。我假设另一个是你的服务器。我建议:

  • 如果您正在运行开发环境,请退出服务器,运行迁移并重新启动服务器。
  • 如果您正在运行生产环境并且需要经常运行期望运行迁移,则可以将#migrate方法添加到服务器应用程序,以便它在同一进程中运行。

(说实话,我刚开始在多处理环境中深入研究PostgreSQL - 如果我了解更多,我会发布一个更好的答案。)