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

Commit 5fc8937

Browse files
committed
Ensure ANALYZE phase is not skipped because of canceled truncate.
Patch b19e425 attempted to preserve existing behavior regarding statistics generation in the case that a truncation attempt was canceled due to lock conflicts. It failed to do this accurately in two regards: (1) autovacuum had previously generated statistics if the truncate attempt failed to initially get the lock rather than having started the attempt, and (2) the VACUUM ANALYZE command had always generated statistics. Both of these changes were unintended, and are reverted by this patch. On review, there seems to be consensus that the previous failure to generate statistics when the truncate was terminated was more an unfortunate consequence of how that effort was previously terminated than a feature we want to keep; so this patch generates statistics even when an autovacuum truncation attempt terminates early. Another unintended change which is kept on the basis that it is an improvement is that when a VACUUM command is truncating, it will the new heuristic for avoiding blocking other processes, rather than keeping an AccessExclusiveLock on the table for however long the truncation takes. Per multiple reports, with some renaming per patch by Jeff Janes. Backpatch to 9.0, where problem was created.
1 parent 91fa853 commit 5fc8937

File tree

1 file changed

+22
-36
lines changed

1 file changed

+22
-36
lines changed

src/backend/commands/vacuumlazy.c

+22-36
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,9 @@
7878
* that the potential for improvement was great enough to merit the cost of
7979
* supporting them.
8080
*/
81-
#define AUTOVACUUM_TRUNCATE_LOCK_CHECK_INTERVAL 20 /* ms */
82-
#define AUTOVACUUM_TRUNCATE_LOCK_WAIT_INTERVAL 50 /* ms */
83-
#define AUTOVACUUM_TRUNCATE_LOCK_TIMEOUT 5000 /* ms */
81+
#define VACUUM_TRUNCATE_LOCK_CHECK_INTERVAL 20 /* ms */
82+
#define VACUUM_TRUNCATE_LOCK_WAIT_INTERVAL 50 /* ms */
83+
#define VACUUM_TRUNCATE_LOCK_TIMEOUT 5000 /* ms */
8484

8585
/*
8686
* Guesstimation of number of dead tuples per page. This is used to
@@ -285,17 +285,10 @@ lazy_vacuum_rel(Relation onerel, VacuumStmt *vacstmt,
285285
new_frozen_xid,
286286
new_min_multi);
287287

288-
/*
289-
* Report results to the stats collector, too. An early terminated
290-
* lazy_truncate_heap attempt suppresses the message and also cancels the
291-
* execution of ANALYZE, if that was ordered.
292-
*/
293-
if (!vacrelstats->lock_waiter_detected)
294-
pgstat_report_vacuum(RelationGetRelid(onerel),
295-
onerel->rd_rel->relisshared,
296-
new_rel_tuples);
297-
else
298-
vacstmt->options &= ~VACOPT_ANALYZE;
288+
/* report results to the stats collector, too */
289+
pgstat_report_vacuum(RelationGetRelid(onerel),
290+
onerel->rd_rel->relisshared,
291+
new_rel_tuples);
299292

300293
/* and log the action if appropriate */
301294
if (IsAutoVacuumWorkerProcess() && Log_autovacuum_min_duration >= 0)
@@ -1347,28 +1340,21 @@ lazy_truncate_heap(Relation onerel, LVRelStats *vacrelstats)
13471340
*/
13481341
CHECK_FOR_INTERRUPTS();
13491342

1350-
if (++lock_retry > (AUTOVACUUM_TRUNCATE_LOCK_TIMEOUT /
1351-
AUTOVACUUM_TRUNCATE_LOCK_WAIT_INTERVAL))
1343+
if (++lock_retry > (VACUUM_TRUNCATE_LOCK_TIMEOUT /
1344+
VACUUM_TRUNCATE_LOCK_WAIT_INTERVAL))
13521345
{
13531346
/*
13541347
* We failed to establish the lock in the specified number of
1355-
* retries. This means we give up truncating. Suppress the
1356-
* ANALYZE step. Doing an ANALYZE at this point will reset the
1357-
* dead_tuple_count in the stats collector, so we will not get
1358-
* called by the autovacuum launcher again to do the truncate.
1348+
* retries. This means we give up truncating.
13591349
*/
13601350
vacrelstats->lock_waiter_detected = true;
1361-
ereport(LOG,
1362-
(errmsg("automatic vacuum of table \"%s.%s.%s\": "
1363-
"could not (re)acquire exclusive "
1364-
"lock for truncate scan",
1365-
get_database_name(MyDatabaseId),
1366-
get_namespace_name(RelationGetNamespace(onerel)),
1351+
ereport(elevel,
1352+
(errmsg("\"%s\": stopping truncate due to conflicting lock request",
13671353
RelationGetRelationName(onerel))));
13681354
return;
13691355
}
13701356

1371-
pg_usleep(AUTOVACUUM_TRUNCATE_LOCK_WAIT_INTERVAL);
1357+
pg_usleep(VACUUM_TRUNCATE_LOCK_WAIT_INTERVAL);
13721358
}
13731359

13741360
/*
@@ -1448,8 +1434,6 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
14481434
{
14491435
BlockNumber blkno;
14501436
instr_time starttime;
1451-
instr_time currenttime;
1452-
instr_time elapsed;
14531437

14541438
/* Initialize the starttime if we check for conflicting lock requests */
14551439
INSTR_TIME_SET_CURRENT(starttime);
@@ -1467,24 +1451,26 @@ count_nondeletable_pages(Relation onerel, LVRelStats *vacrelstats)
14671451
/*
14681452
* Check if another process requests a lock on our relation. We are
14691453
* holding an AccessExclusiveLock here, so they will be waiting. We
1470-
* only do this in autovacuum_truncate_lock_check millisecond
1471-
* intervals, and we only check if that interval has elapsed once
1472-
* every 32 blocks to keep the number of system calls and actual
1473-
* shared lock table lookups to a minimum.
1454+
* only do this once per VACUUM_TRUNCATE_LOCK_CHECK_INTERVAL, and we
1455+
* only check if that interval has elapsed once every 32 blocks to
1456+
* keep the number of system calls and actual shared lock table
1457+
* lookups to a minimum.
14741458
*/
14751459
if ((blkno % 32) == 0)
14761460
{
1461+
instr_time currenttime;
1462+
instr_time elapsed;
1463+
14771464
INSTR_TIME_SET_CURRENT(currenttime);
14781465
elapsed = currenttime;
14791466
INSTR_TIME_SUBTRACT(elapsed, starttime);
14801467
if ((INSTR_TIME_GET_MICROSEC(elapsed) / 1000)
1481-
>= AUTOVACUUM_TRUNCATE_LOCK_CHECK_INTERVAL)
1468+
>= VACUUM_TRUNCATE_LOCK_CHECK_INTERVAL)
14821469
{
14831470
if (LockHasWaitersRelation(onerel, AccessExclusiveLock))
14841471
{
14851472
ereport(elevel,
1486-
(errmsg("\"%s\": suspending truncate "
1487-
"due to conflicting lock request",
1473+
(errmsg("\"%s\": suspending truncate due to conflicting lock request",
14881474
RelationGetRelationName(onerel))));
14891475

14901476
vacrelstats->lock_waiter_detected = true;

0 commit comments

Comments
 (0)