sql - Postgres : Deadlock with 2 update queries

标签 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 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/

相关文章:

mysql - 将 CASE 行与不同的值相乘

sql - 对表中的每一列应用相同的聚合

sql - 在查询中重用 SUM OVER PARTITION 返回值

ruby - 如何使用续集创建数据库

postgresql - Raspberry PI 不监听 5432 端口

postgresql - 是否可以组合 ANY 和 BETWEEN 运算符

sql - 需要根据从表中提取的信息将行插入表中

sql - 在 mysql 中选择使用计数

sql - 像这样的内连接如何转换为Sequelize?

sql - MS Access,如何用子查询中的完整查询替换已保存的查询