我不太理解锁定如何与Postgres事务互动。
当我运行这个(冗长的)查询时,我惊讶于发生的大量锁定:
这个AccessExclusiveLock到底是从哪里来的呢?我猜它是来自TRUNCATE,需要一个AccessExclusiveLock。但是TRUNCATE很快就完成了,所以我希望锁也能很快释放。这让我有几个问题。
当一个命令在事务中获取锁时,该锁是否会在命令结束时(在事务结束之前)被释放?如果是这样,为什么我观察到上述行为?如果不是,为什么不是?实际上,由于事务在COMMIT之前不会触及表格, 那么为什么在事务中的TRUNCATE需要完全阻塞表格呢?
我在PG的交易文档中没有看到任何关于这方面的讨论。
当我运行这个(冗长的)查询时,我惊讶于发生的大量锁定:
BEGIN;
TRUNCATE foo;
\COPY foo FROM 'backup.txt';
COMMIT;
文档中关于\COPY
命令并未提及所需的锁级别,但此帖子表明它只获取RowExclusiveLock。但是,当我在执行\COPY
命令时运行此查询:
SELECT mode, granted FROM pg_locks
WHERE relation='foo'::regclass::oid;
我得到了这个:
mode granted
RowExclusiveLock true
ShareLock true
AccessExclusiveLock true
这个AccessExclusiveLock到底是从哪里来的呢?我猜它是来自TRUNCATE,需要一个AccessExclusiveLock。但是TRUNCATE很快就完成了,所以我希望锁也能很快释放。这让我有几个问题。
当一个命令在事务中获取锁时,该锁是否会在命令结束时(在事务结束之前)被释放?如果是这样,为什么我观察到上述行为?如果不是,为什么不是?实际上,由于事务在COMMIT之前不会触及表格, 那么为什么在事务中的TRUNCATE需要完全阻塞表格呢?
我在PG的交易文档中没有看到任何关于这方面的讨论。
TRUNCATE
如何工作。如果"TRUNCATE
真的清空了表",而"ROLLBACK
不会影响表",那么TRUNCATE
如何被回滚? - Simon LepkinTRUNCATE
时,我的解释有点不一致。如代码所述,旧表不会立即被丢弃,而是在提交时才会被删除,因此在这种情况下,COMMIT
并没有真正触及表格,而是将其移除。我会尝试在我的解释中更清楚地表达这一点。 - Laurenz Albe