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

Commit25e9948

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 parent7b3259b commit25e9948

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,
@@ -3322,7 +3323,49 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
33223323
LockBuffer(buffer,BUFFER_LOCK_EXCLUSIVE);
33233324

33243325
lp=PageGetItemId(page,ItemPointerGetOffsetNumber(otid));
3325-
Assert(ItemIdIsNormal(lp));
3326+
3327+
/*
3328+
* Usually, a buffer pin and/or snapshot blocks pruning of otid, ensuring
3329+
* we see LP_NORMAL here. When the otid origin is a syscache, we may have
3330+
* neither a pin nor a snapshot. Hence, we may see other LP_ states, each
3331+
* of which indicates concurrent pruning.
3332+
*
3333+
* Failing with TM_Updated would be most accurate. However, unlike other
3334+
* TM_Updated scenarios, we don't know the successor ctid in LP_UNUSED and
3335+
* LP_DEAD cases. While the distinction between TM_Updated and TM_Deleted
3336+
* does matter to SQL statements UPDATE and MERGE, those SQL statements
3337+
* hold a snapshot that ensures LP_NORMAL. Hence, the choice between
3338+
* TM_Updated and TM_Deleted affects only the wording of error messages.
3339+
* Settle on TM_Deleted, for two reasons. First, it avoids complicating
3340+
* the specification of when tmfd->ctid is valid. Second, it creates
3341+
* error log evidence that we took this branch.
3342+
*
3343+
* Since it's possible to see LP_UNUSED at otid, it's also possible to see
3344+
* LP_NORMAL for a tuple that replaced LP_UNUSED. If it's a tuple for an
3345+
* unrelated row, we'll fail with "duplicate key value violates unique".
3346+
* XXX if otid is the live, newer version of the newtup row, we'll discard
3347+
* changes originating in versions of this catalog row after the version
3348+
* the caller got from syscache. See syscache-update-pruned.spec.
3349+
*/
3350+
if (!ItemIdIsNormal(lp))
3351+
{
3352+
Assert(RelationSupportsSysCache(RelationGetRelid(relation)));
3353+
3354+
UnlockReleaseBuffer(buffer);
3355+
Assert(!have_tuple_lock);
3356+
if (vmbuffer!=InvalidBuffer)
3357+
ReleaseBuffer(vmbuffer);
3358+
tmfd->ctid=*otid;
3359+
tmfd->xmax=InvalidTransactionId;
3360+
tmfd->cmax=InvalidCommandId;
3361+
3362+
bms_free(hot_attrs);
3363+
bms_free(key_attrs);
3364+
bms_free(id_attrs);
3365+
/* modified_attrs not yet initialized */
3366+
bms_free(interesting_attrs);
3367+
returnTM_Deleted;
3368+
}
33263369

33273370
/*
33283371
* 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