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

Commit3d092fe

Browse files
committed
Avoid unnecessary catalog updates in ALTER SEQUENCE
ALTER SEQUENCE can do nontransactional changes to the sequence (RESTARTclause) and transactional updates to the pg_sequence catalog (most otherclauses). When just calling RESTART, the code would still needlessly doa catalog update without any changes. This would entangle thatoperation in the concurrency issues of a catalog update (causing eitherlocking or concurrency errors, depending on how that issue is to beresolved).Fix by keeping track during options parsing whether a catalog update isneeded, and skip it if not.Reported-by: Jason Petersen <jason@citusdata.com>
1 parenta35ac7c commit3d092fe

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

‎src/backend/commands/sequence.c

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ static Form_pg_sequence_data read_seq_tuple(Relation rel,
101101
staticvoidinit_params(ParseState*pstate,List*options,boolfor_identity,
102102
boolisInit,
103103
Form_pg_sequenceseqform,
104+
bool*changed_seqform,
104105
Form_pg_sequence_dataseqdataform,List**owned_by);
105106
staticvoiddo_setval(Oidrelid,int64next,booliscalled);
106107
staticvoidprocess_owned_by(Relationseqrel,List*owned_by,boolfor_identity);
@@ -115,6 +116,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
115116
{
116117
FormData_pg_sequenceseqform;
117118
FormData_pg_sequence_dataseqdataform;
119+
boolchanged_seqform= false;/* not used here */
118120
List*owned_by;
119121
CreateStmt*stmt=makeNode(CreateStmt);
120122
Oidseqoid;
@@ -153,7 +155,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
153155
}
154156

155157
/* Check and set all option values */
156-
init_params(pstate,seq->options,seq->for_identity, true,&seqform,&seqdataform,&owned_by);
158+
init_params(pstate,seq->options,seq->for_identity, true,&seqform,&changed_seqform,&seqdataform,&owned_by);
157159

158160
/*
159161
* Create relation (and fill value[] and null[] for the tuple)
@@ -418,6 +420,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
418420
Form_pg_sequenceseqform;
419421
Form_pg_sequence_dataseqdata;
420422
FormData_pg_sequence_datanewseqdata;
423+
boolchanged_seqform= false;
421424
List*owned_by;
422425
ObjectAddressaddress;
423426
Relationrel;
@@ -443,7 +446,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
443446
/* lock page' buffer and read tuple into new sequence structure */
444447
seqdata=read_seq_tuple(seqrel,&buf,&seqdatatuple);
445448

446-
/* Copy oldvalues of options into workspace */
449+
/* Copy oldsequence data into workspace */
447450
memcpy(&newseqdata,seqdata,sizeof(FormData_pg_sequence_data));
448451

449452
rel=heap_open(SequenceRelationId,RowExclusiveLock);
@@ -456,7 +459,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
456459
seqform= (Form_pg_sequence)GETSTRUCT(tuple);
457460

458461
/* Check and set new values */
459-
init_params(pstate,stmt->options,stmt->for_identity, false,seqform,&newseqdata,&owned_by);
462+
init_params(pstate,stmt->options,stmt->for_identity, false,seqform,&changed_seqform,&newseqdata,&owned_by);
460463

461464
/* Clear local cache so that we don't think we have cached numbers */
462465
/* Note that we do not change the currval() state */
@@ -507,7 +510,8 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
507510

508511
relation_close(seqrel,NoLock);
509512

510-
CatalogTupleUpdate(rel,&tuple->t_self,tuple);
513+
if (changed_seqform)
514+
CatalogTupleUpdate(rel,&tuple->t_self,tuple);
511515
heap_close(rel,RowExclusiveLock);
512516

513517
returnaddress;
@@ -1213,9 +1217,12 @@ read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
12131217
}
12141218

12151219
/*
1216-
* init_params: process the options list of CREATE or ALTER SEQUENCE,
1217-
* and store the values into appropriate fields of *new. Also set
1218-
* *owned_by to any OWNED BY option, or to NIL if there is none.
1220+
* init_params: process the options list of CREATE or ALTER SEQUENCE, and
1221+
* store the values into appropriate fields of seqform, for changes that go
1222+
* into the pg_sequence catalog, and seqdataform for changes to the sequence
1223+
* relation itself. Set *changed_seqform to true if seqform was changed
1224+
* (interesting for ALTER SEQUENCE). Also set *owned_by to any OWNED BY
1225+
* option, or to NIL if there is none.
12191226
*
12201227
* If isInit is true, fill any unspecified options with default values;
12211228
* otherwise, do not change existing options that aren't explicitly overridden.
@@ -1224,7 +1231,9 @@ static void
12241231
init_params(ParseState*pstate,List*options,boolfor_identity,
12251232
boolisInit,
12261233
Form_pg_sequenceseqform,
1227-
Form_pg_sequence_dataseqdataform,List**owned_by)
1234+
bool*changed_seqform,
1235+
Form_pg_sequence_dataseqdataform,
1236+
List**owned_by)
12281237
{
12291238
DefElem*as_type=NULL;
12301239
DefElem*start_value=NULL;
@@ -1342,6 +1351,8 @@ init_params(ParseState *pstate, List *options, bool for_identity,
13421351
defel->defname);
13431352
}
13441353

1354+
*changed_seqform= false;
1355+
13451356
/*
13461357
* We must reset log_cnt when isInit or when changing any parameters that
13471358
* would affect future nextval allocations.
@@ -1382,37 +1393,50 @@ init_params(ParseState *pstate, List *options, bool for_identity,
13821393
}
13831394

13841395
seqform->seqtypid=newtypid;
1396+
*changed_seqform= true;
13851397
}
13861398
elseif (isInit)
1399+
{
13871400
seqform->seqtypid=INT8OID;
1401+
*changed_seqform= true;
1402+
}
13881403

13891404
/* INCREMENT BY */
13901405
if (increment_by!=NULL)
13911406
{
13921407
seqform->seqincrement=defGetInt64(increment_by);
1408+
*changed_seqform= true;
13931409
if (seqform->seqincrement==0)
13941410
ereport(ERROR,
13951411
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
13961412
errmsg("INCREMENT must not be zero")));
13971413
seqdataform->log_cnt=0;
13981414
}
13991415
elseif (isInit)
1416+
{
14001417
seqform->seqincrement=1;
1418+
*changed_seqform= true;
1419+
}
14011420

14021421
/* CYCLE */
14031422
if (is_cycled!=NULL)
14041423
{
14051424
seqform->seqcycle=intVal(is_cycled->arg);
1425+
*changed_seqform= true;
14061426
Assert(BoolIsValid(seqform->seqcycle));
14071427
seqdataform->log_cnt=0;
14081428
}
14091429
elseif (isInit)
1430+
{
14101431
seqform->seqcycle= false;
1432+
*changed_seqform= true;
1433+
}
14111434

14121435
/* MAXVALUE (null arg means NO MAXVALUE) */
14131436
if (max_value!=NULL&&max_value->arg)
14141437
{
14151438
seqform->seqmax=defGetInt64(max_value);
1439+
*changed_seqform= true;
14161440
seqdataform->log_cnt=0;
14171441
}
14181442
elseif (isInit||max_value!=NULL||reset_max_value)
@@ -1429,6 +1453,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14291453
}
14301454
else
14311455
seqform->seqmax=-1;/* descending seq */
1456+
*changed_seqform= true;
14321457
seqdataform->log_cnt=0;
14331458
}
14341459

@@ -1450,6 +1475,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14501475
if (min_value!=NULL&&min_value->arg)
14511476
{
14521477
seqform->seqmin=defGetInt64(min_value);
1478+
*changed_seqform= true;
14531479
seqdataform->log_cnt=0;
14541480
}
14551481
elseif (isInit||min_value!=NULL||reset_min_value)
@@ -1466,6 +1492,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14661492
}
14671493
else
14681494
seqform->seqmin=1;/* ascending seq */
1495+
*changed_seqform= true;
14691496
seqdataform->log_cnt=0;
14701497
}
14711498

@@ -1499,13 +1526,17 @@ init_params(ParseState *pstate, List *options, bool for_identity,
14991526

15001527
/* START WITH */
15011528
if (start_value!=NULL)
1529+
{
15021530
seqform->seqstart=defGetInt64(start_value);
1531+
*changed_seqform= true;
1532+
}
15031533
elseif (isInit)
15041534
{
15051535
if (seqform->seqincrement>0)
15061536
seqform->seqstart=seqform->seqmin;/* ascending seq */
15071537
else
15081538
seqform->seqstart=seqform->seqmax;/* descending seq */
1539+
*changed_seqform= true;
15091540
}
15101541

15111542
/* crosscheck START */
@@ -1580,6 +1611,7 @@ init_params(ParseState *pstate, List *options, bool for_identity,
15801611
if (cache_value!=NULL)
15811612
{
15821613
seqform->seqcache=defGetInt64(cache_value);
1614+
*changed_seqform= true;
15831615
if (seqform->seqcache <=0)
15841616
{
15851617
charbuf[100];
@@ -1593,7 +1625,10 @@ init_params(ParseState *pstate, List *options, bool for_identity,
15931625
seqdataform->log_cnt=0;
15941626
}
15951627
elseif (isInit)
1628+
{
15961629
seqform->seqcache=1;
1630+
*changed_seqform= true;
1631+
}
15971632
}
15981633

15991634
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp