Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit06bf404

Browse files
Ensure vacuum removes all visibly dead tuples older than OldestXmin
If vacuum fails to remove a tuple with xmax older thanVacuumCutoffs->OldestXmin and younger than GlobalVisState->maybe_needed,it will loop infinitely in lazy_scan_prune(), which compares tuples'visibility information to OldestXmin.Starting in version 14, which uses GlobalVisState for visibility testingduring pruning, it is possible for GlobalVisState->maybe_needed toprecede OldestXmin if maybe_needed is forced to go backward while vacuumis running. This can happen if a disconnected standby with a runningtransaction older than VacuumCutoffs->OldestXmin reconnects to theprimary after vacuum initially calculates GlobalVisState and OldestXmin.Fix this by having vacuum always remove tuples older than OldestXminduring pruning. This is okay because the standby won't replay the tupleremoval until the tuple is removable. Thus, the worst that can happen isa recovery conflict.Fixes BUG# 17257Back-patched in versions 14-17Author: Melanie PlagemanReviewed-by: Noah Misch, Peter Geoghegan, Robert Haas, Andres Freund, and Heikki LinnakangasDiscussion:https://postgr.es/m/CAAKRu_Y_NJzF4-8gzTTeaOuUL3CcGoXPjXcAHbTTygT8AyVqag%40mail.gmail.com
1 parentd97f2ee commit06bf404

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

‎src/backend/access/heap/pruneheap.c

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ typedef struct
3333
{
3434
Relationrel;
3535

36-
/* tuple visibility test, initialized for the relation */
36+
/* State used to test tuple visibility; Initialized for the relation */
37+
TransactionIdoldest_xmin;
3738
GlobalVisState*vistest;
3839

3940
/*
@@ -205,7 +206,8 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
205206
intndeleted,
206207
nnewlpdead;
207208

208-
ndeleted=heap_page_prune(relation,buffer,vistest,limited_xmin,
209+
ndeleted=heap_page_prune(relation,buffer,InvalidTransactionId,
210+
vistest,limited_xmin,
209211
limited_ts,&nnewlpdead,NULL);
210212

211213
/*
@@ -247,11 +249,14 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
247249
* also need to account for a reduction in the length of the line pointer
248250
* array following array truncation by us.
249251
*
250-
* vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD
251-
* (see heap_prune_satisfies_vacuum and
252-
* HeapTupleSatisfiesVacuum). old_snap_xmin / old_snap_ts need to
253-
* either have been set by TransactionIdLimitedForOldSnapshots, or
254-
* InvalidTransactionId/0 respectively.
252+
* vistest and oldest_xmin are used to distinguish whether tuples are DEAD or
253+
* RECENTLY_DEAD (see heap_prune_satisfies_vacuum and
254+
* HeapTupleSatisfiesVacuum). If oldest_xmin is provided by the caller, it is
255+
* used before consulting GlobalVisState.
256+
*
257+
* old_snap_xmin / old_snap_ts need to either have been set by
258+
* TransactionIdLimitedForOldSnapshots, or InvalidTransactionId/0
259+
* respectively.
255260
*
256261
* Sets *nnewlpdead for caller, indicating the number of items that were
257262
* newly set LP_DEAD during prune operation.
@@ -263,6 +268,7 @@ heap_page_prune_opt(Relation relation, Buffer buffer)
263268
*/
264269
int
265270
heap_page_prune(Relationrelation,Bufferbuffer,
271+
TransactionIdoldest_xmin,
266272
GlobalVisState*vistest,
267273
TransactionIdold_snap_xmin,
268274
TimestampTzold_snap_ts,
@@ -290,6 +296,7 @@ heap_page_prune(Relation relation, Buffer buffer,
290296
*/
291297
prstate.new_prune_xid=InvalidTransactionId;
292298
prstate.rel=relation;
299+
prstate.oldest_xmin=oldest_xmin;
293300
prstate.vistest=vistest;
294301
prstate.old_snap_xmin=old_snap_xmin;
295302
prstate.old_snap_ts=old_snap_ts;
@@ -520,13 +527,31 @@ heap_prune_satisfies_vacuum(PruneState *prstate, HeapTuple tup, Buffer buffer)
520527
}
521528

522529
/*
523-
* First check if GlobalVisTestIsRemovableXid() is sufficient to find the
524-
* row dead. If not, and old_snapshot_threshold is enabled, try to use the
525-
* lowered horizon.
530+
* For VACUUM, we must be sure to prune tuples with xmax older than
531+
* oldest_xmin -- a visibility cutoff determined at the beginning of
532+
* vacuuming the relation. oldest_xmin is used for freezing determination
533+
* and we cannot freeze dead tuples' xmaxes.
534+
*/
535+
if (TransactionIdIsValid(prstate->oldest_xmin)&&
536+
NormalTransactionIdPrecedes(dead_after,prstate->oldest_xmin))
537+
returnHEAPTUPLE_DEAD;
538+
539+
/*
540+
* Determine whether or not the tuple is considered dead when compared
541+
* with the provided GlobalVisState. On-access pruning does not provide
542+
* oldest_xmin. And for vacuum, even if the tuple's xmax is not older than
543+
* oldest_xmin, GlobalVisTestIsRemovableXid() could find the row dead if
544+
* the GlobalVisState has been updated since the beginning of vacuuming
545+
* the relation.
526546
*/
527547
if (GlobalVisTestIsRemovableXid(prstate->vistest,dead_after))
528-
res=HEAPTUPLE_DEAD;
529-
elseif (OldSnapshotThresholdActive())
548+
returnHEAPTUPLE_DEAD;
549+
550+
/*
551+
* If GlobalVisTestIsRemovableXid() is not sufficient to find the row dead
552+
* and old_snapshot_threshold is enabled, try to use the lowered horizon.
553+
*/
554+
if (OldSnapshotThresholdActive())
530555
{
531556
/* haven't determined limited horizon yet, requests */
532557
if (!TransactionIdIsValid(prstate->old_snap_xmin))

‎src/backend/access/heap/vacuumlazy.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1581,7 +1581,8 @@ lazy_scan_prune(LVRelState *vacrel,
15811581
* lpdead_items's final value can be thought of as the number of tuples
15821582
* that were deleted from indexes.
15831583
*/
1584-
tuples_deleted=heap_page_prune(rel,buf,vacrel->vistest,
1584+
tuples_deleted=heap_page_prune(rel,buf,vacrel->cutoffs.OldestXmin,
1585+
vacrel->vistest,
15851586
InvalidTransactionId,0,&nnewlpdead,
15861587
&vacrel->offnum);
15871588

‎src/include/access/heapam.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,7 @@ extern TransactionId heap_index_delete_tuples(Relation rel,
285285
structGlobalVisState;
286286
externvoidheap_page_prune_opt(Relationrelation,Bufferbuffer);
287287
externintheap_page_prune(Relationrelation,Bufferbuffer,
288+
TransactionIdoldest_xmin,
288289
structGlobalVisState*vistest,
289290
TransactionIdold_snap_xmin,
290291
TimestampTzold_snap_ts,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp