Postgres:死锁,有2个更新查询

时间:2018-03-25 09:22:12

标签: sql postgresql

我正试图在我们的制作中解决这个死锁问题,现在我真的需要一些帮助。

  

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在事务3603536083上等待ShareLock;受阻   进程60701.进程60701等待事务上的ShareLock   3603536039;被流程60563阻止。

由于死锁进程中只涉及两个事务,因此一个Update如何与另一个Update处于死锁状态。根据我的理解,在第一次更新后,所有这些行上都会有RowExclusiveLock,第二次更新应该被阻止。怎么会有DEADLOCK?

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) ;
  

注意:stream_id是外键。

我能想到的唯一问题是Query1中的子查询,但我怎么也无法弄清楚Select如何成为问题。或者可能是外国约束的东西。

1 个答案:

答案 0 :(得分:1)

第一个查询在进行写锁定之前首先进行读锁定。当第二个查询也等待写锁时,这会导致死锁吗?

尝试for update让子查询获得写锁定吗?

update  ...
from    (
        select  ...
        from    ...
        FOR UPDATE
        ) sg2