2012-04-26 42 views
1

我在包含大量行的表运行在我的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

我能做些什么来完成我的更改?

+0

你怎样开始你的交易?你多久做一次? – vyegorov 2012-04-26 10:02:41

回答

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在多处理环境 - 如果我知道更多,我会发布一个更好的答案)