Re: Improving connection scalability: GetSnapshotData()
Andres Freund <andres@anarazel.de>
Attachments
Hi, SEE BELOW: What, and what not, to do for v13. Attached is a substantially polished version of my patches. Note that the first three patches, as well as the last, are not intended to be committed at this time / in this form - they're there to make testing easier. There is a lot of polish, but also a few substantial changes: - To be compatible with old_snapshot_threshold I've revised the way heap_page_prune_opt() deals with old_snapshot_threshold. Now old_snapshot_threshold is only applied when we otherwise would have been unable to prune (both at the time of the pd_prune_xid check, and on individual tuples). This makes old_snapshot_threshold considerably cheaper and cause less conflicts. This required adding a version of HeapTupleSatisfiesVacuum that returns the horizon, rather than doing the horizon test itself; that way we can first test a tuple's horizon against the normal approximate threshold (making it an accurate threshold if needed) and only if that fails fall back to old_snapshot_threshold. The main reason here was not to improve old_snapshot_threshold, but to avoid a regression when its being used. Because we need a horizon to pass to old_snapshot_threshold, we'd have to fall back to computing an accurate horizon too often. - Previous versions of the patch had a TODO about computing horizons not just for one of shared / catalog / data tables, but all of them at once. To avoid potentially needing to determine xmin horizons multiple times within one transaction. For that I've renamed GetOldestXmin() to ComputeTransactionHorizons() and added wrapper functions instead of the different flag combinations we previously had for GetOldestXmin(). This allows us to get rid of the PROCARRAY_* flags, and PROC_RESERVED. - To address Thomas' review comment about not accessing nextFullXid without xidGenLock, I made latestCompletedXid a FullTransactionId (a fxid is needed to be able to infer 64bit xids for the horizons - otherwise there is some danger they could wrap). - Improving the comment around the snapshot caching, I decided that the justification for correctness around not taking ProcArrayLock is too complicated (in particular around setting MyProc->xmin). While avoiding ProcArrayLock alltogether is a substantial gain, the caching itself helps a lot already. Seems best to leave that for a later step. This means that the numbers for the very high connection counts aren't quite as good. - Plenty of small changes to address issues I found while benchmarking. The only one of real note is that I had released XidGenLock after ProcArrayLock in ProcArrayAdd/Remove. For 2pc that causes noticable unnecessary contention, because we'll wait for XidGenLock while holding ProcArrayLock... I think this is pretty close to being committable. But: This patch came in very late for v13, and it took me much longer to polish it up than I had hoped (partially distraction due to various bugs I found (in particular snapshot_too_old), partially covid19, partially "hell if I know"). The patchset touches core parts of the system. While both Thomas and David have done some review, they haven't for the latest version (mea culpa). In many other instances I would say that the above suggests slipping to v14, given the timing. The main reason I am considering pushing is that I think this patcheset addresses one of the most common critiques of postgres, as well as very common, hard to fix, real-world production issues. GetSnapshotData() has been a major bottleneck for about as long as I have been using postgres, and this addresses that to a significant degree. A second reason I am considering it is that, in my opinion, the changes are not all that complicated and not even that large. At least not for a change to a problem that we've long tried to improve. Obviously we all have a tendency to think our own work is important, and that we deserve a bit more leeway than others. So take the above with a grain of salt. Comments? Greetings, Andres Freund
Commits
-
Try to unbreak 021_row_visibility.pl on mingw.
- 1df2b50dbebb 14.0 landed
-
Fix and test snapshot behavior on standby.
- 7b28913bcab8 14.0 landed
-
Fix race condition in snapshot caching when 2PC is used.
- 07f32fcd23ac 14.0 cited
-
snapshot scalability: cache snapshots using a xact completion counter.
- 623a9ba79bbd 14.0 landed
-
Fix use of wrong index in ComputeXidHorizons().
- f6661d3df228 14.0 landed
-
Make vacuum a bit more verbose to debug BF failure.
- 49967da65aec 14.0 landed
-
snapshot scalability: Introduce dense array of in-progress xids.
- 941697c3c1ae 14.0 landed
-
snapshot scalability: Move PGXACT->vacuumFlags to ProcGlobal->vacuumFlags.
- 5788e258bb26 14.0 landed
-
snapshot scalability: Move subxact info to ProcGlobal, remove PGXACT.
- 73487a60fc10 14.0 landed
-
snapshot scalability: Move PGXACT->xmin back to PGPROC.
- 1f51c17c68d0 14.0 landed
-
snapshot scalability: Don't compute global horizons while building snapshots.
- dc7420c2c927 14.0 landed
-
BRIN: Handle concurrent desummarization properly
- 1f42d35a1d61 14.0 cited
-
Track latest completed xid as a FullTransactionId.
- 3bd7f9969a24 14.0 landed
-
Rename VariableCacheData.nextFullXid to nextXid.
- fea10a64340e 14.0 landed
-
snapshot scalability: Move delayChkpt from PGXACT to PGPROC.
- 75848bc74411 13.0 landed
-
Report progress of CREATE INDEX operations
- ab0dfc961b6a 12.0 cited