Re: Adding REPACK [concurrently]
Antonin Houska <ah@cybertec.at>
Attachments
- v31-0001-Add-REPACK-command.patch (text/x-diff)
Mihail Nikalayeu <mihailnikalayeu@gmail.com> wrote: > Some comments for 0006: > > > SnapBuildSnapshotForRepack(SnapBuild *builder) > Does it also "replays" previously processed WAL to the position that snapshot is ready to use? > I am afraid we may see some non-yet processed parts of WAL leading to duplicate insertion. The changes present in WAL decoded prior the snapshot creation are not replayed - these changes are visible to the snapshot. (This is not really specific to the 0006 part.) > > first_block > What is the reason for that variable? It seems to be always the first block > of relation. Although scan usually starts at the first block, it does not have to, especially due to synchronized sequential scans. > Also, what if we have a huge amount of empty space at the start. In that case the first block will be the block of the first "filled" page. But > insert may (and will) fill empty pages before first_block - out of the range. Good catch! I think I used this "lazy initialization" because I couldn't find the start block in TableScanDesc, and missed the problem that you describe here. > So, I think we should delete it and always use 0 instead. No, we need to set first_block to heapScan->rs_startblock before the scan starts. > > tableScan = table_beginscan(OldHeap, SnapshotAny, 0, (ScanKey) NULL); > With SnapshotAny we are going to check the same tuple multiple times. Better to let scan logic handle it (and change snapshots used by scan > code). The current API does not seem to support changing snapshot of an in-progress scan and I don't want to change that. Plus note that the current implementation of CLUSTER also uses SnapshotAny and then checks the visibility separately. Finally, SnapshotAny is not really an expensive visibility check, if it can be considered a visibility check at all. > > if (blkno >= range_end) > I don't think it is legal to switch a snapshot while holding the tuple. Nothing is protecting it from being pruned\reused. Snapshot protects the table as whole from pruning live (or recently dead) tuples, but when you have fetched a tuple, the containing buffer remains pinned. The buffer pin itself makes prunning of the page impossible. And especially with REPACK (CONCURRENTLY), page pruning is also restricted by the replication slot's xmin. This is increased by calling LogicalIncreaseXminForSlot() from the decoding worker, each time it has created a new snapshot. > > PopActiveSnapshot(); > > InvalidateCatalogSnapshot(); > I think it is a good idea to add here assert for MyProc->xmin and MyProc->xid to be invalid. To ensure we really allow the horizon to advance. I've added it only for xmin. xid is valid because REPACK is executed in a transaction. That reminds me that PROC_IN_VACUUM should be present in MyProc->statusFlags. Fixed. > > /* Set to request a snapshot. */ > > bool snapshot_requested; > We know the end or region in advance, so it should be possible to filter before writing changes to file. Yes, filtering before writing makes sense, I'll consider that. > So, it is some kind of "this is the end of region, create new file and store everything before + create new snapshot for me". The last se of changes does not have to be followed by a snapshot - that's the purpose of snapshot_requested. > > PopActiveSnapshot(); > Sometimes without InvalidateCatalogSnapshot(). [ It'd be a bit easier to find the code if you included hunk headers. ] heapam_relation_copy_for_cluster() does not access catalogs after the first invalidation. The following comment is related: /* * XXX It might be worth Assert(CatalogSnapshot == NULL) here, * however that symbol is not external. */ > > PushActiveSnapshot(GetTransactionSnapshot()); > GetLatestSnapshot() feels better here. What will then happen to code that uses GetActiveSnapshot() ? > > * The individual builds might still be a problem, but that's a > > * separate issue. > Opening the index may create a catalog snapshot, so it needs to be invalidated after. It'll be invalidated in the next iteration. The point of this invalidation is to use one snapshot per index. > > * TODO Can we somehow use the fact that the new heap is not yet > > * visible to other transaction, and thus cannot be vacuumed? > Snapshot resetting [0] may work here (without CIC, just as part of the scan + some code to ensure catalog snapshot is managed correctly). > Also, to correctly build a unique index - some tech from [0] is required (building a unique index with multiple snapshots is a little bit tricky). > Or we may implement some super lightweight way - just SnapshotAny without any visibility checks (just assume everything is ok since it > copied from another relation with the same index set). ok, I'll check your patch. > > This approach introduces one limitation though: if the USING INDEX clause is > > specified, an explicit sort is always used. Index scan wouldn't work because > > it does not return the tuples sorted by CTID. > > Technically we may just use keys (if they are comparable) as a way to specify regions. Instead of number of pages to switch snapshot - > number of tuples or time. > But because we don't know the region end in advance - we have to keep all the changes in file and filter only while applying. Good idea. Unfortunately it questions your proposal to filter the changes before writing, as suggested above. > > range_end = repack_blocks_per_snapshot; > Should be repack_blocks_per_snapshot + ctx->first_block ? Indeed, I also failed to avoid assuming first_block==0 :-) > > * XXX It might be worth Assert(CatalogSnapshot == NULL) > > * here, however that symbol is not external. > As said above - better assert for MyProc->xmin/xid + add InvalidateCatalogSnapshot. I proposed the Assert above, but still thinking about it. > > Is REPACKED (CONCURRENTLY) is being run by this backend? > REPACK and double "is" Other comments accepted. Thanks. -- Antonin Houska Web: https://www.cybertec-postgresql.com
Commits
GET /api/v1/messages/:b64id/commits
the thread's linked commits as JSON, with link sources.
API reference →
-
Allow old WAL recycling during REPACK CONCURRENTLY
- 45b02984e2fa 19 (unreleased) landed
-
Advance restart_lsn more eagerly in LogicalConfirmReceivedLocation
- 38470c2c1ea7 19 (unreleased) landed
-
Remove unnecessary signal handler change
- 5d48d3b14e0e 19 (unreleased) landed
-
Improve REPACK (CONCURRENTLY) error messages some more
- 378dffaf8c80 19 (unreleased) landed
-
Revert "Allow logical replication snapshots to be database-specific"
- 01a80f062146 19 (unreleased) landed
-
Move REPACK (CONCURRENTLY) test out of stock regression tests
- 4b2aa4b39cba 19 (unreleased) landed
-
REPACK: do not require REPLICATION or LOGIN
- 5dbb63fc82b7 19 (unreleased) landed
-
Add missing initialization
- 05c401d5786a 19 (unreleased) landed
-
Simplify declaration of memcpy target
- 2cff363715ef 19 (unreleased) landed
-
Reserve replication slots specifically for REPACK
- e76d8c749c31 19 (unreleased) landed
-
doc: Add an example of REPACK (CONCURRENTLY)
- 8fb95a8ab6e5 19 (unreleased) landed
-
Allow logical replication snapshots to be database-specific
- 0d3dba38c777 19 (unreleased) landed
-
Avoid different-size pointer-to-integer cast
- a3b069ef90bd 19 (unreleased) landed
-
Fix valgrind failure
- 5bcc3fbd196c 19 (unreleased) landed
-
Add CONCURRENTLY option to REPACK
- 28d534e2ae0a 19 (unreleased) landed
-
Rename cluster.c to repack.c (and corresponding .h)
- c0b53ec06309 19 (unreleased) landed
-
Allow index_create to suppress index_build progress reporting
- caec9d9fadf1 19 (unreleased) landed
-
Make index_concurrently_create_copy more general
- 33bf7318f94c 19 (unreleased) landed
-
Document the 'command' column of pg_stat_progress_repack
- a630ac5c2016 19 (unreleased) landed
-
Introduce the REPACK command
- ac58465e0618 19 (unreleased) landed
-
Toggle logical decoding dynamically based on logical slot presence.
- 67c20979ce72 19 (unreleased) cited
-
Split vacuumdb to create vacuuming.c/h
- c4067383cb2c 19 (unreleased) landed
-
Remove ReorderBufferTupleBuf structure.
- 08e6344fd642 17.0 cited
-
Revert changes to CONCURRENTLY that "sped up" Xmin advance
- 042b584c7f7d 14.4 cited
-
VACUUM: ignore indexing operations with CONCURRENTLY
- d9d076222f5b 14.0 cited