admin管理员组

文章数量:1305117

Truncate isn't waiting for the release of a select lock before placing an exclusive lock on the target, so no other selects can execute concurrently. Is there any documentation on this behavior?

You need 3 sessions to see this behavior.

tab 1 (manual transactions):

begin;
select * from tbl;

tab 2:

truncate tbl; --stalls (expected)

tab 3:

select * from tbl; --stalls (unexpected)

Truncate isn't waiting for the release of a select lock before placing an exclusive lock on the target, so no other selects can execute concurrently. Is there any documentation on this behavior?

You need 3 sessions to see this behavior.

tab 1 (manual transactions):

begin;
select * from tbl;

tab 2:

truncate tbl; --stalls (expected)

tab 3:

select * from tbl; --stalls (unexpected)
Share Improve this question asked Feb 3 at 20:33 user433342user433342 1,0501 gold badge10 silver badges34 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

The lock queues are documented in detail in src/backend/storage/lmgr/README:

Lock acquisition (routines LockAcquire and ProcSleep) follows these rules:

1. A lock request is granted immediately if it does not conflict with
any existing or waiting lock request, or if the process already holds an
instance of the same lock type (eg, there's no penalty to acquire a read
lock twice).  Note that a process never conflicts with itself, eg one
can obtain read lock when one already holds exclusive lock.

2. Otherwise the process joins the lock's wait queue.  Normally it will
be added to the end of the queue, but there is an exception: if the
process already holds locks on this same lockable object that conflict
with the request of any pending waiter, then the process will be
inserted in the wait queue just ahead of the first such waiter.  (If we
did not make this check, the deadlock detection code would adjust the
queue order to resolve the conflict, but it's relatively cheap to make
the check in ProcSleep and avoid a deadlock timeout delay in this case.)
Note special case when inserting before the end of the queue: if the
process's request does not conflict with any existing lock nor any
waiting request before its insertion point, then go ahead and grant the
lock without waiting.

Which table lock block which other is documented here.

That TRUNCATE requires an ACCESS EXCLUSIVE lock is documented here.

Some tips how to avoid problems with these locks:

  • keep your transactions and queries short
  • set lock_timeout to a low value before running statements like TRUNCATE that take high locks — on error, repeat until you succeed

本文标签: postgresqlWhy does postgres truncate lock a table while waiting for a lockStack Overflow