【问题标题】:Why does postgres lock one table when inserting into another为什么postgres在插入另一个表时会锁定一个表
【发布时间】:2019-09-11 10:44:23
【问题描述】:

我的名为 Event 的源表位于不同的数据库中,它有数百万行。每个事件都可以有一个 DELETE、UPDATE 或 NEW 操作。

我们有一个 Java 进程,它按照事件的创建顺序处理这些事件并执行各种规则,然后将结果插入到多个表中以进行查找、分析等。

我现在正在使用 JdbcTemplate 并使用 batchUpdate 按顺序删除和更新 Postgres DB,但我也希望能够并行。每批有 1000 个要插入/更新或删除的实体。

但是,目前即使是按顺序执行,Postgres 也会以某种方式锁定查询,我不太了解以及为什么。

这里是一些代码

            entityService.deleteBatch(deletedEntities);
            indexingService.deleteBatch(deletedEntities);

...
            entityService.updateBatch(allActiveEntities);
            indexingService.updateBatch(....);

这些服务中的每一个都在不同的表中执行插入/删除操作。不过他们是在一笔交易中。

以下查询

SELECT
    activity.pid,
    activity.usename,
    activity.query,
    blocking.pid AS blocking_id,
    blocking.query AS blocking_query
FROM pg_stat_activity AS activity
         JOIN pg_stat_activity AS blocking ON blocking.pid = ANY(pg_blocking_pids(activity.pid));

返回

Query being blocked: "insert INTO ENTITY (reference, seq, data) VALUES($1, $2, $3) ON CONFLICT ON CONSTRAINT ENTITY_c DO UPDATE SET data = $4",
Blockking query: delete from ENTITY_INDEX where reference = $1 

这些表之间没有外来约束。我们确实有索引,因此我们可以在流程中运行查询以进行处理。

为什么一个完全不同的表会阻塞其他表?我们该如何解决这个问题?

【问题讨论】:

    标签: database postgresql


    【解决方案1】:

    您的查询具有误导性。

    它所显示的“阻塞查询”实际上是阻塞事务中运行的最后一条语句。

    可能是同一事务中的前一条语句导致entity(或者更确切地说是其中的一行)被锁定。

    【讨论】:

    • 感谢您的快速回答。一切都在事务中,并使用 Spring JdbcTemplate 中的 batchUpdate 按顺序运行。那为什么会有东西被锁起来呢?是否有任何我确定的日志?
    • 您可以在postgresql.conf中设置log_min_duration_statement = 0,并设置log_line_prefix包含pid和事务ID,然后就可以挖掘日志文件了。
    猜你喜欢
    • 1970-01-01
    • 2014-05-15
    • 1970-01-01
    • 2023-01-11
    • 2021-04-25
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多