运行 一个简单的更新时 PostgreSQL 中的死锁
Deadlocks in PostgreSQL when running a simple UPDATE
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" = , "updated_at" = WHERE "cities"."id" =
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 日志。
两个这样的事务很容易死锁。
为避免该问题,请确保当您“循环遍历城市”时,始终以相同的顺序进行,使用类似:
FOR c IN
SELECT * FROM city
WHERE /* whatever */
ORDER BY city.id
LOOP
/* perform the update */
END LOOP;
要查找锁定更新查询的内容,可以使用
SELECT pg_blocking_pids(<pid of the query that is locked>);
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" = , "updated_at" = WHERE "cities"."id" =
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 日志。
两个这样的事务很容易死锁。
为避免该问题,请确保当您“循环遍历城市”时,始终以相同的顺序进行,使用类似:
FOR c IN
SELECT * FROM city
WHERE /* whatever */
ORDER BY city.id
LOOP
/* perform the update */
END LOOP;
要查找锁定更新查询的内容,可以使用
SELECT pg_blocking_pids(<pid of the query that is locked>);