运行简单的UPDATE时在PostgreSQL中出现死锁

问题描述 投票:0回答:1

update cities set cdb_data = NULL, updated_at = now() where cities.id = 1;

我们遍历城市并使用cdb_data作为rails代码的一部分来更新城市,但是不断出现以下错误。

ActiveRecord::StatementInvalid: PG::TRDeadlockDetected: ERROR:  deadlock detected
DETAIL:  Process 26741 waits for ShareLock on transaction 2970537161; blocked by process 26818.
Process 26818 waits for ShareLock on transaction 2970537053; blocked by process 26741.
HINT:  See server log for query details.
CONTEXT:  while updating tuple (39,15) in relation "cities"
UPDATE "cities" SET "cdb_data" = $1, "updated_at" = $2 WHERE "cities"."id" = $3

更新城市对象的Ruby代码

    city              = City.find_or_create_by(uuid: city_data['uuid'])
    city.name         = city_data['name']
    city.state_id     = city_data['state_id']
    city.cdb_data     = city_data
    city.save

我不知道此错误发生在哪条记录上,为什么?即使将生产转储放在本地或暂存中,这似乎也不会发生。任何帮助将不胜感激。

我正在heroku上运行服务器,因此我不确定我是否可以看到postgres日志。

ruby-on-rails postgresql ruby-on-rails-5 postgresql-9.5 database-deadlocks
1个回答
2
投票

两个这样的事务很容易陷入僵局。

为了避免该问题,请确保当您“遍历城市”时,始终使用相同的顺序,例如:

FOR c IN
   SELECT * FROM city
   WHERE /* whatever */
   ORDER BY city.id
LOOP
   /* perform the update */
END LOOP;

0
投票

两个这样的事务很容易陷入僵局。

为了避免该问题,请确保当您“遍历城市”时,始终使用相同的顺序,例如:

FOR c IN
   SELECT * FROM city
   WHERE /* whatever */
   ORDER BY city.id
LOOP
   /* perform the update */
END LOOP;
© www.soinside.com 2019 - 2024. All rights reserved.