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

Commitdc02b98

Browse files
committed
At update of non-LP_NORMAL TID, fail instead of corrupting page header.
The right mix of DDL and VACUUM could corrupt a catalog page header suchthat PageIsVerified() durably fails, requiring a restore from backup.This affects only catalogs that both have a syscache and have DDL codethat uses syscache tuples to construct updates. One of the testpermutations shows a variant not yet fixed.This makes !TransactionIdIsValid(TM_FailureData.xmax) possible withTM_Deleted. I think core and PGXN are indifferent to that.Per bug #17821 from Alexander Lakhin. Back-patch to v13 (all supportedversions). The test case is v17+, since it uses INJECTION_POINT.Discussion:https://postgr.es/m/17821-dd8c334263399284@postgresql.org
1 parent216294b commitdc02b98

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

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

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
#include"utils/relcache.h"
7373
#include"utils/snapmgr.h"
7474
#include"utils/spccache.h"
75+
#include"utils/syscache.h"
7576

7677

7778
staticHeapTupleheap_prepare_insert(Relationrelation,HeapTupletup,
@@ -3242,7 +3243,49 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
32423243
LockBuffer(buffer,BUFFER_LOCK_EXCLUSIVE);
32433244

32443245
lp=PageGetItemId(page,ItemPointerGetOffsetNumber(otid));
3245-
Assert(ItemIdIsNormal(lp));
3246+
3247+
/*
3248+
* Usually, a buffer pin and/or snapshot blocks pruning of otid, ensuring
3249+
* we see LP_NORMAL here. When the otid origin is a syscache, we may have
3250+
* neither a pin nor a snapshot. Hence, we may see other LP_ states, each
3251+
* of which indicates concurrent pruning.
3252+
*
3253+
* Failing with TM_Updated would be most accurate. However, unlike other
3254+
* TM_Updated scenarios, we don't know the successor ctid in LP_UNUSED and
3255+
* LP_DEAD cases. While the distinction between TM_Updated and TM_Deleted
3256+
* does matter to SQL statements UPDATE and MERGE, those SQL statements
3257+
* hold a snapshot that ensures LP_NORMAL. Hence, the choice between
3258+
* TM_Updated and TM_Deleted affects only the wording of error messages.
3259+
* Settle on TM_Deleted, for two reasons. First, it avoids complicating
3260+
* the specification of when tmfd->ctid is valid. Second, it creates
3261+
* error log evidence that we took this branch.
3262+
*
3263+
* Since it's possible to see LP_UNUSED at otid, it's also possible to see
3264+
* LP_NORMAL for a tuple that replaced LP_UNUSED. If it's a tuple for an
3265+
* unrelated row, we'll fail with "duplicate key value violates unique".
3266+
* XXX if otid is the live, newer version of the newtup row, we'll discard
3267+
* changes originating in versions of this catalog row after the version
3268+
* the caller got from syscache. See syscache-update-pruned.spec.
3269+
*/
3270+
if (!ItemIdIsNormal(lp))
3271+
{
3272+
Assert(RelationSupportsSysCache(RelationGetRelid(relation)));
3273+
3274+
UnlockReleaseBuffer(buffer);
3275+
Assert(!have_tuple_lock);
3276+
if (vmbuffer!=InvalidBuffer)
3277+
ReleaseBuffer(vmbuffer);
3278+
tmfd->ctid=*otid;
3279+
tmfd->xmax=InvalidTransactionId;
3280+
tmfd->cmax=InvalidCommandId;
3281+
3282+
bms_free(hot_attrs);
3283+
bms_free(key_attrs);
3284+
bms_free(id_attrs);
3285+
/* modified_attrs not yet initialized */
3286+
bms_free(interesting_attrs);
3287+
returnTM_Deleted;
3288+
}
32463289

32473290
/*
32483291
* Fill in enough data in oldtup for HeapDetermineColumnsInfo to work

‎src/include/access/tableam.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ typedef enum TM_Result
113113
*
114114
* xmax is the outdating transaction's XID. If the caller wants to visit the
115115
* replacement tuple, it must check that this matches before believing the
116-
* replacement is really a match.
116+
* replacement is really a match. This is InvalidTransactionId if the target
117+
* was !LP_NORMAL (expected only for a TID retrieved from syscache).
117118
*
118119
* cmax is the outdating command's CID, but only when the failure code is
119120
* TM_SelfModified (i.e., something in the current transaction outdated the

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp