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

Commit0408e1e

Browse files
committed
Do not select new object OIDs that match recently-dead entries.
When selecting a new OID, we take care to avoid picking one that's alreadyin use in the target table, so as not to create duplicates after the OIDcounter has wrapped around. However, up to now we used SnapshotDirty whenscanning for pre-existing entries. That ignores committed-dead rows, sothat we could select an OID matching a deleted-but-not-yet-vacuumed row.While that mostly worked, it has two problems:* If recently deleted, the dead row might still be visible to MVCCsnapshots, creating a risk for duplicate OIDs when examining the catalogswithin our own transaction. Such duplication couldn't be visible outsidethe object-creating transaction, though, and we've heard few if any fieldreports corresponding to such a symptom.* When selecting a TOAST OID, deleted toast rows definitely *are* visibleto SnapshotToast, and will remain so until vacuumed away. This leads toa conflict that will manifest in errors like "unexpected chunk number 0(expected 1) for toast value nnnnn". We've been seeing reports of sucherrors from the field for years, but the cause was unclear before.The fix is simple: just use SnapshotAny to search for conflicting rows.This results in a slightly longer window before object OIDs can berecycled, but that seems unlikely to create any large problems.Pavan DeolaseeDiscussion:https://postgr.es/m/CABOikdOgWT2hHkYG3Wwo2cyZJq2zfs1FH0FgX-=h4OLosXHf9w@mail.gmail.com
1 parent811969b commit0408e1e

File tree

2 files changed

+12
-11
lines changed

2 files changed

+12
-11
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,9 @@ toast_delete_datum(Relation rel, Datum value, bool is_speculative)
17941794
/* ----------
17951795
* toastrel_valueid_exists -
17961796
*
1797-
*Test whether a toast value with the given ID exists in the toast relation
1797+
*Test whether a toast value with the given ID exists in the toast relation.
1798+
*For safety, we consider a value to exist if there are either live or dead
1799+
*toast rows with that ID; see notes for GetNewOid().
17981800
* ----------
17991801
*/
18001802
staticbool
@@ -1806,7 +1808,6 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
18061808
intnum_indexes;
18071809
intvalidIndex;
18081810
Relation*toastidxs;
1809-
SnapshotDataSnapshotToast;
18101811

18111812
/* Fetch a valid index relation */
18121813
validIndex=toast_open_indexes(toastrel,
@@ -1825,10 +1826,9 @@ toastrel_valueid_exists(Relation toastrel, Oid valueid)
18251826
/*
18261827
* Is there any such chunk?
18271828
*/
1828-
init_toast_snapshot(&SnapshotToast);
18291829
toastscan=systable_beginscan(toastrel,
18301830
RelationGetRelid(toastidxs[validIndex]),
1831-
true,&SnapshotToast,1,&toastkey);
1831+
true,SnapshotAny,1,&toastkey);
18321832

18331833
if (systable_getnext(toastscan)!=NULL)
18341834
result= true;

‎src/backend/catalog/catalog.c

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,12 @@ IsSharedRelation(Oid relationId)
282282
* managed to cycle through 2^32 OIDs and generate the same OID before we
283283
* finish inserting our row. This seems unlikely to be a problem. Note
284284
* that if we had to *commit* the row to end the race condition, the risk
285-
* would be rather higher; therefore we use SnapshotDirty in the test,
286-
* so that we will see uncommitted rows.
285+
* would be rather higher; therefore we use SnapshotAny in the test, so that
286+
* we will see uncommitted rows. (We used to use SnapshotDirty, but that has
287+
* the disadvantage that it ignores recently-deleted rows, creating a risk
288+
* of transient conflicts for as long as our own MVCC snapshots think a
289+
* recently-deleted row is live. The risk is far higher when selecting TOAST
290+
* OIDs, because SnapshotToast considers dead rows as active indefinitely.)
287291
*/
288292
Oid
289293
GetNewOid(Relationrelation)
@@ -336,7 +340,6 @@ Oid
336340
GetNewOidWithIndex(Relationrelation,OidindexId,AttrNumberoidcolumn)
337341
{
338342
OidnewOid;
339-
SnapshotDataSnapshotDirty;
340343
SysScanDescscan;
341344
ScanKeyDatakey;
342345
boolcollides;
@@ -349,8 +352,6 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
349352
*/
350353
Assert(!IsBinaryUpgrade||RelationGetRelid(relation)!=TypeRelationId);
351354

352-
InitDirtySnapshot(SnapshotDirty);
353-
354355
/* Generate new OIDs until we find one not in the table */
355356
do
356357
{
@@ -363,9 +364,9 @@ GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
363364
BTEqualStrategyNumber,F_OIDEQ,
364365
ObjectIdGetDatum(newOid));
365366

366-
/* see notes above about usingSnapshotDirty */
367+
/* see notes above about usingSnapshotAny */
367368
scan=systable_beginscan(relation,indexId, true,
368-
&SnapshotDirty,1,&key);
369+
SnapshotAny,1,&key);
369370

370371
collides=HeapTupleIsValid(systable_getnext(scan));
371372

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp