我正在努力解决我们生产中的这个僵局问题,现在我真的需要一些帮助。
PostgreSQL 9.5.10
查询 1:(更新 1000 条记录)
update entitlements.stream_general sg
set stream_offset_id =nextval( 'entitlements.stream_general_stream_offset_id_seq' ),
should_update_offset_id = false
from (select id, topic, stream_id from entitlements.stream_general where should_update_offset_id = true limit 1000) sg2
where sg.id=sg2.id and sg.topic=sg2.topic and sg.stream_id = sg2.stream_id
查询 2:(更新单个记录)
update entitlements.stream_general set stream_action = $1::entitlements.stream_action_type, update_dt = now(), should_update_offset_id = true where stream_id = $2 and topic = $3 and id = $4
异常:
Process 60563 waits for ShareLock on transaction 3603536083; blocked by process 60701. Process 60701 waits for ShareLock on transaction 3603536039; blocked by process 60563.
既然死锁过程中只涉及两个事务,一个Update怎么可能和另一个Update死锁。根据我的理解,在第一次更新之后,所有这些行上都会有 RowExclusiveLock,第二次更新应该被阻止。怎么会死锁呢?
stream_general
表架构:
CREATE TABLE entitlements.stream_general (
stream_id int4 NOT NULL,
id varchar NOT NULL,
topic varchar NOT NULL,
stream_offset_id int8 NOT NULL DEFAULT '-1'::integer,
create_dt timestamptz NOT NULL DEFAULT now(),
update_dt timestamptz NOT NULL DEFAULT now(),
stream_action stream_action_type NOT NULL,
should_update_offset_id bool NULL,
PRIMARY KEY (stream_id, topic, id),
FOREIGN KEY (stream_id) REFERENCES entitlements.stream(stream_id) ON DELETE CASCADE
)
WITH (
OIDS=FALSE
) ;
CREATE INDEX stream_general_id_idx ON entitlements.stream_general USING btree (id, topic) ;
CREATE INDEX stream_general_should_update_offset_id_index ON entitlements.stream_general USING btree (should_update_offset_id) ;
CREATE INDEX stream_general_stream_id_idx ON entitlements.stream_general USING btree (stream_id, topic, stream_offset_id) ;
Note : stream_id is the foreign key.
我唯一能想到的罪魁祸首是 Query1 中的子查询,但我无法弄清楚 Select 是如何产生问题的。或者可能是由于外国限制而发生的事情。
最佳答案
第一个查询是先拿读锁再拿写锁。当第二个查询也在等待写锁时,这会导致死锁吗?
尝试 for update
让子查询获取写锁?
update ...
from (
select ...
from ...
FOR UPDATE
) sg2
关于sql - Postgres : Deadlock with 2 update queries,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49474321/