Content-Length: 353417 | pFad | http://github.com/postgres/postgres/commit/75b8982eae78f930cc8c1c48cd2d9dc03113d92b

98 Use SnapshotDirty when checking for conflicting index names. · postgres/postgres@75b8982 · GitHub
Skip to content

Commit 75b8982

Browse files
committed
Use SnapshotDirty when checking for conflicting index names.
While choosing an autogenerated name for an index, look for pre-existing relations using a SnapshotDirty snapshot, instead of the previous behavior that considered only committed-good pg_class rows. This allows us to detect and avoid conflicts against indexes that are still being built. It's still possible to fail due to a race condition, but the window is now just the amount of time that it takes DefineIndex to validate all its parameters, call smgrcreate(), and enter the index's pg_class row. Formerly the race window covered the entire time needed to create and fill an index, which could be very long if the table is large. Worse, if the conflicting index creation is part of a larger transaction, it wouldn't be visible till COMMIT. So this isn't a complete solution, but it should greatly ameliorate the problem, and the patch is simple enough to be back-patchable. It might at some point be useful to do the same for pg_constraint entries (cf. ChooseConstraintName, ConstraintNameExists, and related functions). However, in the absence of field complaints, I'll leave that alone for now. The relation-name test should be good enough for index-based constraints, while foreign-key constraints seem to be okay since they require exclusive locks to create. Bug: #18959 Reported-by: Maximilian Chrzan <maximilian.chrzan@here.com> Author: Tom Lane <tgl@sss.pgh.pa.us> Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com> Discussion: https://postgr.es/m/18959-f63b53b864bb1417@postgresql.org Backpatch-through: 13
1 parent fc0fb77 commit 75b8982

File tree

1 file changed

+36
-2
lines changed

1 file changed

+36
-2
lines changed

src/backend/commands/indexcmds.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2402,7 +2402,9 @@ makeObjectName(const char *name1, const char *name2, const char *label)
24022402
* constraint names.)
24032403
*
24042404
* Note: it is theoretically possible to get a collision anyway, if someone
2405-
* else chooses the same name concurrently. This is fairly unlikely to be
2405+
* else chooses the same name concurrently. We shorten the race condition
2406+
* window by checking for conflicting relations using SnapshotDirty, but
2407+
* that doesn't close the window entirely. This is fairly unlikely to be
24062408
* a problem in practice, especially if one is holding an exclusive lock on
24072409
* the relation identified by name1. However, if choosing multiple names
24082410
* within a single command, you'd better create the new object and do
@@ -2418,15 +2420,45 @@ ChooseRelationName(const char *name1, const char *name2,
24182420
int pass = 0;
24192421
char *relname = NULL;
24202422
char modlabel[NAMEDATALEN];
2423+
SnapshotData SnapshotDirty;
2424+
Relation pgclassrel;
2425+
2426+
/* prepare to search pg_class with a dirty snapshot */
2427+
InitDirtySnapshot(SnapshotDirty);
2428+
pgclassrel = table_open(RelationRelationId, AccessShareLock);
24212429

24222430
/* try the unmodified label first */
24232431
strlcpy(modlabel, label, sizeof(modlabel));
24242432

24252433
for (;;)
24262434
{
2435+
ScanKeyData key[2];
2436+
SysScanDesc scan;
2437+
bool collides;
2438+
24272439
relname = makeObjectName(name1, name2, modlabel);
24282440

2429-
if (!OidIsValid(get_relname_relid(relname, namespaceid)))
2441+
/* is there any conflicting relation name? */
2442+
ScanKeyInit(&key[0],
2443+
Anum_pg_class_relname,
2444+
BTEqualStrategyNumber, F_NAMEEQ,
2445+
CStringGetDatum(relname));
2446+
ScanKeyInit(&key[1],
2447+
Anum_pg_class_relnamespace,
2448+
BTEqualStrategyNumber, F_OIDEQ,
2449+
ObjectIdGetDatum(namespaceid));
2450+
2451+
scan = systable_beginscan(pgclassrel, ClassNameNspIndexId,
2452+
true /* indexOK */ ,
2453+
&SnapshotDirty,
2454+
2, key);
2455+
2456+
collides = HeapTupleIsValid(systable_getnext(scan));
2457+
2458+
systable_endscan(scan);
2459+
2460+
/* break out of loop if no conflict */
2461+
if (!collides)
24302462
{
24312463
if (!isconstraint ||
24322464
!ConstraintNameExists(relname, namespaceid))
@@ -2438,6 +2470,8 @@ ChooseRelationName(const char *name1, const char *name2,
24382470
snprintf(modlabel, sizeof(modlabel), "%s%d", label, ++pass);
24392471
}
24402472

2473+
table_close(pgclassrel, AccessShareLock);
2474+
24412475
return relname;
24422476
}
24432477

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgres/postgres/commit/75b8982eae78f930cc8c1c48cd2d9dc03113d92b

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy