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

Commit5861b1f

Browse files
committed
Use SnapshotDirty when checking for conflicting index names.
While choosing an autogenerated name for an index, look forpre-existing relations using a SnapshotDirty snapshot, instead of theprevious behavior that considered only committed-good pg_class rows.This allows us to detect and avoid conflicts against indexes that arestill being built.It's still possible to fail due to a race condition, but the windowis now just the amount of time that it takes DefineIndex to validateall its parameters, call smgrcreate(), and enter the index's pg_classrow. Formerly the race window covered the entire time needed tocreate and fill an index, which could be very long if the table islarge. Worse, if the conflicting index creation is part of a largertransaction, it wouldn't be visible till COMMIT.So this isn't a complete solution, but it should greatly amelioratethe problem, and the patch is simple enough to be back-patchable.It might at some point be useful to do the same for pg_constraintentries (cf. ChooseConstraintName, ConstraintNameExists, and relatedfunctions). However, in the absence of field complaints, I'll leavethat alone for now. The relation-name test should be good enough forindex-based constraints, while foreign-key constraints seem to be okaysince they require exclusive locks to create.Bug: #18959Reported-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.orgBackpatch-through: 13
1 parent2f6e240 commit5861b1f

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
@@ -2592,7 +2592,9 @@ makeObjectName(const char *name1, const char *name2, const char *label)
25922592
* constraint names.)
25932593
*
25942594
* Note: it is theoretically possible to get a collision anyway, if someone
2595-
* else chooses the same name concurrently. This is fairly unlikely to be
2595+
* else chooses the same name concurrently. We shorten the race condition
2596+
* window by checking for conflicting relations using SnapshotDirty, but
2597+
* that doesn't close the window entirely. This is fairly unlikely to be
25962598
* a problem in practice, especially if one is holding an exclusive lock on
25972599
* the relation identified by name1. However, if choosing multiple names
25982600
* within a single command, you'd better create the new object and do
@@ -2608,15 +2610,45 @@ ChooseRelationName(const char *name1, const char *name2,
26082610
intpass=0;
26092611
char*relname=NULL;
26102612
charmodlabel[NAMEDATALEN];
2613+
SnapshotDataSnapshotDirty;
2614+
Relationpgclassrel;
2615+
2616+
/* prepare to search pg_class with a dirty snapshot */
2617+
InitDirtySnapshot(SnapshotDirty);
2618+
pgclassrel=table_open(RelationRelationId,AccessShareLock);
26112619

26122620
/* try the unmodified label first */
26132621
strlcpy(modlabel,label,sizeof(modlabel));
26142622

26152623
for (;;)
26162624
{
2625+
ScanKeyDatakey[2];
2626+
SysScanDescscan;
2627+
boolcollides;
2628+
26172629
relname=makeObjectName(name1,name2,modlabel);
26182630

2619-
if (!OidIsValid(get_relname_relid(relname,namespaceid)))
2631+
/* is there any conflicting relation name? */
2632+
ScanKeyInit(&key[0],
2633+
Anum_pg_class_relname,
2634+
BTEqualStrategyNumber,F_NAMEEQ,
2635+
CStringGetDatum(relname));
2636+
ScanKeyInit(&key[1],
2637+
Anum_pg_class_relnamespace,
2638+
BTEqualStrategyNumber,F_OIDEQ,
2639+
ObjectIdGetDatum(namespaceid));
2640+
2641+
scan=systable_beginscan(pgclassrel,ClassNameNspIndexId,
2642+
true/* indexOK */ ,
2643+
&SnapshotDirty,
2644+
2,key);
2645+
2646+
collides=HeapTupleIsValid(systable_getnext(scan));
2647+
2648+
systable_endscan(scan);
2649+
2650+
/* break out of loop if no conflict */
2651+
if (!collides)
26202652
{
26212653
if (!isconstraint||
26222654
!ConstraintNameExists(relname,namespaceid))
@@ -2628,6 +2660,8 @@ ChooseRelationName(const char *name1, const char *name2,
26282660
snprintf(modlabel,sizeof(modlabel),"%s%d",label,++pass);
26292661
}
26302662

2663+
table_close(pgclassrel,AccessShareLock);
2664+
26312665
returnrelname;
26322666
}
26332667

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp