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

Commit ab6eaee

Browse files
committed
When VACUUM or ANALYZE skips a concurrently dropped table, log it.
Hopefully, the additional logging will help avoid confusion that could otherwise result. Nathan Bossart, reviewed by Michael Paquier, Fabrízio Mello, and me
1 parent ecc27d5 commit ab6eaee

File tree

6 files changed

+208
-13
lines changed

6 files changed

+208
-13
lines changed

doc/src/sgml/config.sgml

+2-2
Original file line numberDiff line numberDiff line change
@@ -5926,8 +5926,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
59265926
<literal>250ms</literal> then all automatic vacuums and analyzes that run
59275927
250ms or longer will be logged. In addition, when this parameter is
59285928
set to any value other than <literal>-1</literal>, a message will be
5929-
logged if an autovacuum action is skipped due to the existence of a
5930-
conflicting lock. Enabling this parameter can be helpful
5929+
logged if an autovacuum action is skipped due to a conflicting lock or a
5930+
concurrently dropped relation. Enabling this parameter can be helpful
59315931
in tracking autovacuum activity. This parameter can only be set in
59325932
the <filename>postgresql.conf</filename> file or on the server command line;
59335933
but the setting can be overridden for individual tables by

src/backend/commands/analyze.c

+41-5
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ analyze_rel(Oid relid, RangeVar *relation, int options,
120120
int elevel;
121121
AcquireSampleRowsFunc acquirefunc = NULL;
122122
BlockNumber relpages = 0;
123+
bool rel_lock = true;
123124

124125
/* Select logging level */
125126
if (options & VACOPT_VERBOSE)
@@ -149,15 +150,50 @@ analyze_rel(Oid relid, RangeVar *relation, int options,
149150
else
150151
{
151152
onerel = NULL;
152-
if (relation &&
153-
IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
154-
ereport(LOG,
153+
rel_lock = false;
154+
}
155+
156+
/*
157+
* If we failed to open or lock the relation, emit a log message before
158+
* exiting.
159+
*/
160+
if (!onerel)
161+
{
162+
/*
163+
* If the RangeVar is not defined, we do not have enough information
164+
* to provide a meaningful log statement. Chances are that
165+
* analyze_rel's caller has intentionally not provided this
166+
* information so that this logging is skipped, anyway.
167+
*/
168+
if (relation == NULL)
169+
return;
170+
171+
/*
172+
* Determine the log level. For autovacuum logs, we emit a LOG if
173+
* log_autovacuum_min_duration is not disabled. For manual ANALYZE,
174+
* we emit a WARNING to match the log statements in the permissions
175+
* checks.
176+
*/
177+
if (!IsAutoVacuumWorkerProcess())
178+
elevel = WARNING;
179+
else if (params->log_min_duration >= 0)
180+
elevel = LOG;
181+
else
182+
return;
183+
184+
if (!rel_lock)
185+
ereport(elevel,
155186
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
156187
errmsg("skipping analyze of \"%s\" --- lock not available",
157188
relation->relname)));
158-
}
159-
if (!onerel)
189+
else
190+
ereport(elevel,
191+
(errcode(ERRCODE_UNDEFINED_TABLE),
192+
errmsg("skipping analyze of \"%s\" --- relation no longer exists",
193+
relation->relname)));
194+
160195
return;
196+
}
161197

162198
/*
163199
* Check permissions --- this should match vacuum's check!

src/backend/commands/vacuum.c

+43-6
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
13301330
Oid save_userid;
13311331
int save_sec_context;
13321332
int save_nestlevel;
1333+
bool rel_lock = true;
13331334

13341335
Assert(params != NULL);
13351336

@@ -1400,16 +1401,52 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
14001401
else
14011402
{
14021403
onerel = NULL;
1403-
if (relation &&
1404-
IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
1405-
ereport(LOG,
1406-
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
1407-
errmsg("skipping vacuum of \"%s\" --- lock not available",
1408-
relation->relname)));
1404+
rel_lock = false;
14091405
}
14101406

1407+
/*
1408+
* If we failed to open or lock the relation, emit a log message before
1409+
* exiting.
1410+
*/
14111411
if (!onerel)
14121412
{
1413+
int elevel = 0;
1414+
1415+
/*
1416+
* Determine the log level.
1417+
*
1418+
* If the RangeVar is not defined, we do not have enough information
1419+
* to provide a meaningful log statement. Chances are that
1420+
* vacuum_rel's caller has intentionally not provided this information
1421+
* so that this logging is skipped, anyway.
1422+
*
1423+
* Otherwise, for autovacuum logs, we emit a LOG if
1424+
* log_autovacuum_min_duration is not disabled. For manual VACUUM, we
1425+
* emit a WARNING to match the log statements in the permission
1426+
* checks.
1427+
*/
1428+
if (relation != NULL)
1429+
{
1430+
if (!IsAutoVacuumWorkerProcess())
1431+
elevel = WARNING;
1432+
else if (params->log_min_duration >= 0)
1433+
elevel = LOG;
1434+
}
1435+
1436+
if (elevel != 0)
1437+
{
1438+
if (!rel_lock)
1439+
ereport(elevel,
1440+
(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
1441+
errmsg("skipping vacuum of \"%s\" --- lock not available",
1442+
relation->relname)));
1443+
else
1444+
ereport(elevel,
1445+
(errcode(ERRCODE_UNDEFINED_TABLE),
1446+
errmsg("skipping vacuum of \"%s\" --- relation no longer exists",
1447+
relation->relname)));
1448+
}
1449+
14131450
PopActiveSnapshot();
14141451
CommitTransactionCommand();
14151452
return false;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
Parsed test spec with 2 sessions
2+
3+
starting permutation: lock vac_specified drop_and_commit
4+
step lock:
5+
BEGIN;
6+
LOCK test1 IN SHARE MODE;
7+
8+
step vac_specified: VACUUM test1, test2; <waiting ...>
9+
step drop_and_commit:
10+
DROP TABLE test2;
11+
COMMIT;
12+
13+
WARNING: skipping vacuum of "test2" --- relation no longer exists
14+
step vac_specified: <... completed>
15+
16+
starting permutation: lock vac_all drop_and_commit
17+
step lock:
18+
BEGIN;
19+
LOCK test1 IN SHARE MODE;
20+
21+
step vac_all: VACUUM; <waiting ...>
22+
step drop_and_commit:
23+
DROP TABLE test2;
24+
COMMIT;
25+
26+
step vac_all: <... completed>
27+
28+
starting permutation: lock analyze_specified drop_and_commit
29+
step lock:
30+
BEGIN;
31+
LOCK test1 IN SHARE MODE;
32+
33+
step analyze_specified: ANALYZE test1, test2; <waiting ...>
34+
step drop_and_commit:
35+
DROP TABLE test2;
36+
COMMIT;
37+
38+
WARNING: skipping analyze of "test2" --- relation no longer exists
39+
step analyze_specified: <... completed>
40+
41+
starting permutation: lock analyze_all drop_and_commit
42+
step lock:
43+
BEGIN;
44+
LOCK test1 IN SHARE MODE;
45+
46+
step analyze_all: ANALYZE; <waiting ...>
47+
step drop_and_commit:
48+
DROP TABLE test2;
49+
COMMIT;
50+
51+
step analyze_all: <... completed>
52+
53+
starting permutation: lock vac_analyze_specified drop_and_commit
54+
step lock:
55+
BEGIN;
56+
LOCK test1 IN SHARE MODE;
57+
58+
step vac_analyze_specified: VACUUM ANALYZE test1, test2; <waiting ...>
59+
step drop_and_commit:
60+
DROP TABLE test2;
61+
COMMIT;
62+
63+
WARNING: skipping vacuum of "test2" --- relation no longer exists
64+
step vac_analyze_specified: <... completed>
65+
66+
starting permutation: lock vac_analyze_all drop_and_commit
67+
step lock:
68+
BEGIN;
69+
LOCK test1 IN SHARE MODE;
70+
71+
step vac_analyze_all: VACUUM ANALYZE; <waiting ...>
72+
step drop_and_commit:
73+
DROP TABLE test2;
74+
COMMIT;
75+
76+
step vac_analyze_all: <... completed>

src/test/isolation/isolation_schedule

+1
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,4 @@ test: sequence-ddl
6262
test: async-notify
6363
test: vacuum-reltuples
6464
test: timeouts
65+
test: vacuum-concurrent-drop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Test for log messages emitted by VACUUM and ANALYZE when a specified
2+
# relation is concurrently dropped.
3+
#
4+
# This also verifies that log messages are not emitted for concurrently
5+
# dropped relations that were not specified in the VACUUM or ANALYZE
6+
# command.
7+
8+
setup
9+
{
10+
CREATE TABLE test1 (a INT);
11+
CREATE TABLE test2 (a INT);
12+
}
13+
14+
teardown
15+
{
16+
DROP TABLE IF EXISTS test1;
17+
DROP TABLE IF EXISTS test2;
18+
}
19+
20+
session "s1"
21+
step "lock"
22+
{
23+
BEGIN;
24+
LOCK test1 IN SHARE MODE;
25+
}
26+
step "drop_and_commit"
27+
{
28+
DROP TABLE test2;
29+
COMMIT;
30+
}
31+
32+
session "s2"
33+
step "vac_specified" { VACUUM test1, test2; }
34+
step "vac_all" { VACUUM; }
35+
step "analyze_specified" { ANALYZE test1, test2; }
36+
step "analyze_all" { ANALYZE; }
37+
step "vac_analyze_specified" { VACUUM ANALYZE test1, test2; }
38+
step "vac_analyze_all" { VACUUM ANALYZE; }
39+
40+
permutation "lock" "vac_specified" "drop_and_commit"
41+
permutation "lock" "vac_all" "drop_and_commit"
42+
permutation "lock" "analyze_specified" "drop_and_commit"
43+
permutation "lock" "analyze_all" "drop_and_commit"
44+
permutation "lock" "vac_analyze_specified" "drop_and_commit"
45+
permutation "lock" "vac_analyze_all" "drop_and_commit"

0 commit comments

Comments
 (0)