You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中Truncate等待锁时为何会锁定表?

PostgreSQL Truncate等待锁时阻塞后续SELECT的原因及官方说明

问题背景

你观察到的现象是:当TRUNCATE操作因等待锁而阻塞时,后续的SELECT请求也会被卡住,这是PostgreSQL锁机制与TRUNCATE锁要求共同作用的结果。

原因解析

TRUNCATE属于DDL范畴操作,它需要获取目标表的ACCESS EXCLUSIVE锁——这是PostgreSQL中最严格的锁级别,与所有其他锁模式(包括普通SELECT使用的ACCESS SHARE锁)完全不兼容。

当会话2发起TRUNCATE请求时,由于会话1的未提交事务持有该表的ACCESS SHARE锁,会话2会进入锁等待队列。而PostgreSQL的锁请求按到达顺序处理,后续会话3的SELECT请求需要的ACCESS SHARE锁,会被排在会话2的ACCESS EXCLUSIVE锁请求之后。因为两种锁模式互斥,会话3必须等会话2的锁请求完成(要么拿到锁执行Truncate,要么等待超时)才能继续,这就造成了后续SELECT被阻塞的现象。

官方文档依据

PostgreSQL官方文档对该行为有明确说明:

  1. TRUNCATE的锁要求:TRUNCATE会在操作的每个表上获取ACCESS EXCLUSIVE锁,这会阻塞所有其他对该表的并发操作。
  2. 锁模式兼容性:ACCESS EXCLUSIVE锁与所有其他锁模式(包括SELECT使用的ACCESS SHARE)互斥,任何需要该锁的操作都会等待所有现有锁释放,同时后续的锁请求会排队等待该锁操作完成。
  3. 锁队列机制:锁请求按到达顺序处理,高优先级锁的等待会阻塞后续所有不兼容的锁请求,无法绕过等待队列直接获取锁。

复现步骤

会话1(持有表锁的手动事务)

begin;
select * from tbl;

(事务保持打开状态,持续持有ACCESS SHARE锁)

会话2(发起Truncate进入等待)

truncate tbl; -- 预期会阻塞,等待会话1释放锁

会话3(后续SELECT被意外阻塞)

select * from tbl; -- 因锁队列顺序被阻塞

内容的提问来源于stack exchange,提问作者user433342

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 14:55:13