Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 47167b7

Browse files
Reduce lock levels for ALTER TABLE SET autovacuum storage options
Reduce lock levels down to ShareUpdateExclusiveLock for all autovacuum-related relation options when setting them using ALTER TABLE. Add infrastructure to allow varying lock levels for relation options in later patches. Setting multiple options together uses the highest lock level required for any option. Works for both main and toast tables. Fabrízio Mello, reviewed by Michael Paquier, mild edit and additional regression tests from myself
1 parent f16d522 commit 47167b7

File tree

6 files changed

+219
-43
lines changed

6 files changed

+219
-43
lines changed

doc/src/sgml/ref/alter_table.sgml

+4
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,10 @@ ALTER TABLE ALL IN TABLESPACE <replaceable class="PARAMETER">name</replaceable>
543543
of <command>ALTER TABLE</> that forces a table rewrite.
544544
</para>
545545

546+
<para>
547+
Changing autovacuum storage parameters acquires a <literal>SHARE UPDATE EXCLUSIVE</literal> lock.
548+
</para>
549+
546550
<note>
547551
<para>
548552
While <command>CREATE TABLE</> allows <literal>OIDS</> to be specified

src/backend/access/common/reloptions.c

+114-30
Original file line numberDiff line numberDiff line change
@@ -57,31 +57,35 @@ static relopt_bool boolRelOpts[] =
5757
{
5858
"autovacuum_enabled",
5959
"Enables autovacuum in this relation",
60-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
60+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
61+
ShareUpdateExclusiveLock
6162
},
6263
true
6364
},
6465
{
6566
{
6667
"user_catalog_table",
6768
"Declare a table as an additional catalog table, e.g. for the purpose of logical replication",
68-
RELOPT_KIND_HEAP
69+
RELOPT_KIND_HEAP,
70+
AccessExclusiveLock
6971
},
7072
false
7173
},
7274
{
7375
{
7476
"fastupdate",
7577
"Enables \"fast update\" feature for this GIN index",
76-
RELOPT_KIND_GIN
78+
RELOPT_KIND_GIN,
79+
AccessExclusiveLock
7780
},
7881
true
7982
},
8083
{
8184
{
8285
"security_barrier",
8386
"View acts as a row security barrier",
84-
RELOPT_KIND_VIEW
87+
RELOPT_KIND_VIEW,
88+
AccessExclusiveLock
8589
},
8690
false
8791
},
@@ -95,140 +99,158 @@ static relopt_int intRelOpts[] =
9599
{
96100
"fillfactor",
97101
"Packs table pages only to this percentage",
98-
RELOPT_KIND_HEAP
102+
RELOPT_KIND_HEAP,
103+
AccessExclusiveLock
99104
},
100105
HEAP_DEFAULT_FILLFACTOR, HEAP_MIN_FILLFACTOR, 100
101106
},
102107
{
103108
{
104109
"fillfactor",
105110
"Packs btree index pages only to this percentage",
106-
RELOPT_KIND_BTREE
111+
RELOPT_KIND_BTREE,
112+
AccessExclusiveLock
107113
},
108114
BTREE_DEFAULT_FILLFACTOR, BTREE_MIN_FILLFACTOR, 100
109115
},
110116
{
111117
{
112118
"fillfactor",
113119
"Packs hash index pages only to this percentage",
114-
RELOPT_KIND_HASH
120+
RELOPT_KIND_HASH,
121+
AccessExclusiveLock
115122
},
116123
HASH_DEFAULT_FILLFACTOR, HASH_MIN_FILLFACTOR, 100
117124
},
118125
{
119126
{
120127
"fillfactor",
121128
"Packs gist index pages only to this percentage",
122-
RELOPT_KIND_GIST
129+
RELOPT_KIND_GIST,
130+
AccessExclusiveLock
123131
},
124132
GIST_DEFAULT_FILLFACTOR, GIST_MIN_FILLFACTOR, 100
125133
},
126134
{
127135
{
128136
"fillfactor",
129137
"Packs spgist index pages only to this percentage",
130-
RELOPT_KIND_SPGIST
138+
RELOPT_KIND_SPGIST,
139+
AccessExclusiveLock
131140
},
132141
SPGIST_DEFAULT_FILLFACTOR, SPGIST_MIN_FILLFACTOR, 100
133142
},
134143
{
135144
{
136145
"autovacuum_vacuum_threshold",
137146
"Minimum number of tuple updates or deletes prior to vacuum",
138-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
147+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
148+
ShareUpdateExclusiveLock
139149
},
140150
-1, 0, INT_MAX
141151
},
142152
{
143153
{
144154
"autovacuum_analyze_threshold",
145155
"Minimum number of tuple inserts, updates or deletes prior to analyze",
146-
RELOPT_KIND_HEAP
156+
RELOPT_KIND_HEAP,
157+
ShareUpdateExclusiveLock
147158
},
148159
-1, 0, INT_MAX
149160
},
150161
{
151162
{
152163
"autovacuum_vacuum_cost_delay",
153164
"Vacuum cost delay in milliseconds, for autovacuum",
154-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
165+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
166+
ShareUpdateExclusiveLock
155167
},
156168
-1, 0, 100
157169
},
158170
{
159171
{
160172
"autovacuum_vacuum_cost_limit",
161173
"Vacuum cost amount available before napping, for autovacuum",
162-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
174+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
175+
ShareUpdateExclusiveLock
163176
},
164177
-1, 1, 10000
165178
},
166179
{
167180
{
168181
"autovacuum_freeze_min_age",
169182
"Minimum age at which VACUUM should freeze a table row, for autovacuum",
170-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
183+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
184+
ShareUpdateExclusiveLock
171185
},
172186
-1, 0, 1000000000
173187
},
174188
{
175189
{
176190
"autovacuum_multixact_freeze_min_age",
177191
"Minimum multixact age at which VACUUM should freeze a row multixact's, for autovacuum",
178-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
192+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
193+
ShareUpdateExclusiveLock
179194
},
180195
-1, 0, 1000000000
181196
},
182197
{
183198
{
184199
"autovacuum_freeze_max_age",
185200
"Age at which to autovacuum a table to prevent transaction ID wraparound",
186-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
201+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
202+
ShareUpdateExclusiveLock
187203
},
188204
-1, 100000000, 2000000000
189205
},
190206
{
191207
{
192208
"autovacuum_multixact_freeze_max_age",
193209
"Multixact age at which to autovacuum a table to prevent multixact wraparound",
194-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
210+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
211+
ShareUpdateExclusiveLock
195212
},
196213
-1, 100000000, 2000000000
197214
},
198215
{
199216
{
200217
"autovacuum_freeze_table_age",
201218
"Age at which VACUUM should perform a full table sweep to freeze row versions",
202-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
219+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
220+
ShareUpdateExclusiveLock
203221
}, -1, 0, 2000000000
204222
},
205223
{
206224
{
207225
"autovacuum_multixact_freeze_table_age",
208226
"Age of multixact at which VACUUM should perform a full table sweep to freeze row versions",
209-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
227+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
228+
ShareUpdateExclusiveLock
210229
}, -1, 0, 2000000000
211230
},
212231
{
213232
{
214233
"log_autovacuum_min_duration",
215234
"Sets the minimum execution time above which autovacuum actions will be logged",
216-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
235+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
236+
ShareUpdateExclusiveLock
217237
},
218238
-1, -1, INT_MAX
219239
},
220240
{
221241
{
222242
"pages_per_range",
223243
"Number of pages that each page range covers in a BRIN index",
224-
RELOPT_KIND_BRIN
244+
RELOPT_KIND_BRIN,
245+
AccessExclusiveLock
225246
}, 128, 1, 131072
226247
},
227248
{
228249
{
229250
"gin_pending_list_limit",
230251
"Maximum size of the pending list for this GIN index, in kilobytes.",
231-
RELOPT_KIND_GIN
252+
RELOPT_KIND_GIN,
253+
AccessExclusiveLock
232254
},
233255
-1, 64, MAX_KILOBYTES
234256
},
@@ -243,47 +265,53 @@ static relopt_real realRelOpts[] =
243265
{
244266
"autovacuum_vacuum_scale_factor",
245267
"Number of tuple updates or deletes prior to vacuum as a fraction of reltuples",
246-
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST
268+
RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
269+
ShareUpdateExclusiveLock
247270
},
248271
-1, 0.0, 100.0
249272
},
250273
{
251274
{
252275
"autovacuum_analyze_scale_factor",
253276
"Number of tuple inserts, updates or deletes prior to analyze as a fraction of reltuples",
254-
RELOPT_KIND_HEAP
277+
RELOPT_KIND_HEAP,
278+
ShareUpdateExclusiveLock
255279
},
256280
-1, 0.0, 100.0
257281
},
258282
{
259283
{
260284
"seq_page_cost",
261285
"Sets the planner's estimate of the cost of a sequentially fetched disk page.",
262-
RELOPT_KIND_TABLESPACE
286+
RELOPT_KIND_TABLESPACE,
287+
AccessExclusiveLock
263288
},
264289
-1, 0.0, DBL_MAX
265290
},
266291
{
267292
{
268293
"random_page_cost",
269294
"Sets the planner's estimate of the cost of a nonsequentially fetched disk page.",
270-
RELOPT_KIND_TABLESPACE
295+
RELOPT_KIND_TABLESPACE,
296+
AccessExclusiveLock
271297
},
272298
-1, 0.0, DBL_MAX
273299
},
274300
{
275301
{
276302
"n_distinct",
277303
"Sets the planner's estimate of the number of distinct values appearing in a column (excluding child relations).",
278-
RELOPT_KIND_ATTRIBUTE
304+
RELOPT_KIND_ATTRIBUTE,
305+
AccessExclusiveLock
279306
},
280307
0, -1.0, DBL_MAX
281308
},
282309
{
283310
{
284311
"n_distinct_inherited",
285312
"Sets the planner's estimate of the number of distinct values appearing in a column (including child relations).",
286-
RELOPT_KIND_ATTRIBUTE
313+
RELOPT_KIND_ATTRIBUTE,
314+
AccessExclusiveLock
287315
},
288316
0, -1.0, DBL_MAX
289317
},
@@ -297,7 +325,8 @@ static relopt_string stringRelOpts[] =
297325
{
298326
"buffering",
299327
"Enables buffering build for this GiST index",
300-
RELOPT_KIND_GIST
328+
RELOPT_KIND_GIST,
329+
AccessExclusiveLock
301330
},
302331
4,
303332
false,
@@ -308,7 +337,8 @@ static relopt_string stringRelOpts[] =
308337
{
309338
"check_option",
310339
"View has WITH CHECK OPTION defined (local or cascaded).",
311-
RELOPT_KIND_VIEW
340+
RELOPT_KIND_VIEW,
341+
AccessExclusiveLock
312342
},
313343
0,
314344
true,
@@ -344,13 +374,29 @@ initialize_reloptions(void)
344374

345375
j = 0;
346376
for (i = 0; boolRelOpts[i].gen.name; i++)
377+
{
378+
Assert(DoLockModesConflict(boolRelOpts[i].gen.lockmode,
379+
boolRelOpts[i].gen.lockmode));
347380
j++;
381+
}
348382
for (i = 0; intRelOpts[i].gen.name; i++)
383+
{
384+
Assert(DoLockModesConflict(intRelOpts[i].gen.lockmode,
385+
intRelOpts[i].gen.lockmode));
349386
j++;
387+
}
350388
for (i = 0; realRelOpts[i].gen.name; i++)
389+
{
390+
Assert(DoLockModesConflict(realRelOpts[i].gen.lockmode,
391+
realRelOpts[i].gen.lockmode));
351392
j++;
393+
}
352394
for (i = 0; stringRelOpts[i].gen.name; i++)
395+
{
396+
Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
397+
stringRelOpts[i].gen.lockmode));
353398
j++;
399+
}
354400
j += num_custom_options;
355401

356402
if (relOpts)
@@ -1411,3 +1457,41 @@ tablespace_reloptions(Datum reloptions, bool validate)
14111457

14121458
return (bytea *) tsopts;
14131459
}
1460+
1461+
/*
1462+
* Determine the required LOCKMODE from an option list.
1463+
*
1464+
* Called from AlterTableGetLockLevel(), see that function
1465+
* for a longer explanation of how this works.
1466+
*/
1467+
LOCKMODE
1468+
AlterTableGetRelOptionsLockLevel(List *defList)
1469+
{
1470+
LOCKMODE lockmode = NoLock;
1471+
ListCell *cell;
1472+
1473+
if (defList == NIL)
1474+
return AccessExclusiveLock;
1475+
1476+
if (need_initialization)
1477+
initialize_reloptions();
1478+
1479+
foreach(cell, defList)
1480+
{
1481+
DefElem *def = (DefElem *) lfirst(cell);
1482+
int i;
1483+
1484+
for (i = 0; relOpts[i]; i++)
1485+
{
1486+
if (pg_strncasecmp(relOpts[i]->name,
1487+
def->defname,
1488+
relOpts[i]->namelen + 1) == 0)
1489+
{
1490+
if (lockmode < relOpts[i]->lockmode)
1491+
lockmode = relOpts[i]->lockmode;
1492+
}
1493+
}
1494+
}
1495+
1496+
return lockmode;
1497+
}

src/backend/commands/tablecmds.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -3038,16 +3038,12 @@ AlterTableGetLockLevel(List *cmds)
30383038
* are set here for tables, views and indexes; for historical
30393039
* reasons these can all be used with ALTER TABLE, so we can't
30403040
* decide between them using the basic grammar.
3041-
*
3042-
* XXX Look in detail at each option to determine lock level,
3043-
* e.g. cmd_lockmode = GetRelOptionsLockLevel((List *)
3044-
* cmd->def);
30453041
*/
30463042
case AT_SetRelOptions: /* Uses MVCC in getIndexes() and
30473043
* getTables() */
30483044
case AT_ResetRelOptions: /* Uses MVCC in getIndexes() and
30493045
* getTables() */
3050-
cmd_lockmode = AccessExclusiveLock;
3046+
cmd_lockmode = AlterTableGetRelOptionsLockLevel((List *) cmd->def);
30513047
break;
30523048

30533049
default: /* oops */

0 commit comments

Comments
 (0)