PostgreSQL中执行TRUNCATE大表时无法看到对应表的锁信息
问题描述
我正在对一个容量达数TB的大表执行TRUNCATE操作,为确认不存在锁问题,我在另一个窗口执行了如下查询,但结果中未显示被截断表的锁信息,请问这是为什么?
查询语句:
select c.relname, l.locktype, l.pid, l.mode, l.granted FROM pg_locks l JOIN pg_class c ON l.relation = c.oid;
查询结果:
relname | locktype | pid | mode | granted -----------------------------------+----------+------+-----------------+--------- pg_class_tblspc_relfilenode_index | relation | 6931 | AccessShareLock | t pg_class_relname_nsp_index | relation | 6931 | AccessShareLock | t pg_class_oid_index | relation | 6931 | AccessShareLock | t pg_class | relation | 6931 | AccessShareLock | t pg_locks | relation | 6931 | AccessShareLock | t
原因分析
TRUNCATE锁持有时间极短:PostgreSQL中
TRUNCATE属于DDL操作,它会先获取目标表的ACCESS EXCLUSIVE锁,但这个锁仅在修改表元数据、清理目录项的阶段持有。对于大表,实际的磁盘文件清理是后台异步执行的,锁会在这一步开始前就被释放。如果你的查询是在锁释放后执行的,自然看不到目标表的锁记录。查询未覆盖完整命名空间:你的查询通过
JOIN pg_class关联表名,但如果目标表不在当前search_path指定的模式下,或者未显式匹配表所在的命名空间,可能无法通过relname匹配到目标表。可以修改查询,显示完整的表名(含模式)来排查:select n.nspname || '.' || c.relname as full_relname, l.locktype, l.pid, l.mode, l.granted, l.relation FROM pg_locks l LEFT JOIN pg_class c ON l.relation = c.oid LEFT JOIN pg_namespace n ON c.relnamespace = n.oid;TRUNCATE操作已完成:如果
TRUNCATE已经执行完毕(包括后台清理流程),锁会被彻底释放,查询结果中不会留存相关记录。可以通过查询目标表的行数、磁盘占用量来确认操作是否结束。
内容的提问来源于stack exchange,提问作者Jayadevan
相关产品推荐
相关产品推荐

