| From: | Antonin Houska <ah(at)cybertec(dot)at> |
|---|---|
| To: | shihao zhong <zhong950419(at)gmail(dot)com> |
| Cc: | pgsql-hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, alvherre(at)kurilemu(dot)de |
| Subject: | Re: REPACK (CONCURRENTLY): do not block the table while waiting for the final lock |
| Date: | 2026-10-06 18:32:29 |
| Message-ID: | 91610.1791311549@localhost |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
shihao zhong <zhong950419(at)gmail(dot)com> wrote:
> Subject: REPACK (CONCURRENTLY): do not block the table while waiting for the final lock
[ I assume this is not meant for v19, is it? ]
>
> REPACK (CONCURRENTLY) requests AccessExclusiveLock at the end to swap
> the files. While it is queued for that lock behind a long running
> transaction, every new query on the table queues behind it. On master I
> held AccessShareLock in one session for 15 seconds, and a single row
> SELECT that arrived while REPACK was waiting took 14.7 seconds. The
> usual defense, lock_timeout, makes it worse here. With lock_timeout = 3s
> the REPACK fails after all the copying is done.
>
> The attached patch makes REPACK stop queueing for that lock. It checks
> whether the lock is available. While it is not, it applies the changes
> that arrived meanwhile and checks again every 50 ms, the way
> lazy_truncate_heap() does. With the patch the same SELECT took 0.9
> seconds, and REPACK finished once the long transaction ended.
> lock_timeout limits how long it keeps trying, so its meaning does not
> change.
>
> The cost is on the REPACK side. A conditional request only succeeds when
> nobody holds a lock at that moment, so on a busy table it can take a
> while. With 16 pgbench clients doing single row SELECTs on the table
> (about 135k tps), REPACK needed 1 to 10 seconds to get the lock, against
> 0.5 seconds when queueing. After hours of copying I think that is fine.
>
> There is a variant with a lock manager change that queues for
> deadlock_timeout at a time and then leaves the queue.
Waiting for a limited time would make more sense, but why exactly
deadlock_timeout should control that?
Attached is my proposal to restrict the wait time, w/o hacking the lock
manager. Note that it deliberately does not teach REPACK to give up. Unlike
(lazy) VACUUM, all the work is rolled back if REPACK ends with ERROR.
--
Antonin Houska
Web: https://www.cybertec-postgresql.com
| Attachment | Content-Type | Size |
|---|---|---|
| 0001-Limit-the-time-for-REPACK-CONCURRENTLY-to-stay-in-th.patch | text/x-diff | 3.7 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Robert Treat | 2026-10-06 18:32:33 | Re: Teach pg_upgrade to deal with invalid databases |
| Previous Message | Tomas Vondra | 2026-10-06 18:26:00 | Re: [PATCH] Fix segmentation fault caused by reentrancy in RI_Fkey_cascade_del (ri_triggers.c) |