Thread
-
Re: autovacuum truncate exclusive lock round two
Kevin Grittner <kgrittn@mail.com> — 2012-12-04T18:51:13Z
Jan Wieck wrote: > [arguments for GUCs] This is getting confusing. I thought I had already conceded the case for autovacuum_truncate_lock_try, and you appeared to spend most of your post arguing for it anyway. I think. It's a little hard to tell. Perhaps the best thing is to present the issue to the list and solicit more opinions on what to do. Please correct me if I mis-state any of this. The primary problem this patch is solving is that in some workloads, autovacuum will repeatedly try to truncate the unused pages at the end of a table, but will continually get canceled after burning resources because another process wants to acquire a lock on the table which conflicts with the one held by autovacuum. This is handled by the deadlock checker, so another process must block for the deadlock_timeout interval each time. All work done by the truncate phase of autovacuum is lost on each interrupted attempt. Statistical information is not updated, so another attempt will trigger the next time autovacuum looks at whether to vacuum the table. It's obvious that this pattern not only fails to release potentially large amounts of unused space back to the OS, but the headbanging can continue to consume significant resources and for an extended period, and the repeated blocking for deadlock_timeout could cause latency problems. The patch has the truncate work, which requires AccessExclusiveLock, check at intervals for whether another process is waiting on its lock. That interval is one of the timings we need to determine, and for which a GUC was initially proposed. I think that the check should be fast enough that doing it once every 20ms as a hard-coded interval would be good enough. When it sees this situation, it truncates the file for as far as it has managed to get, releases its lock on the table, sleeps for an interval, and then checks to see if the lock has become available again. How long it should sleep between tries to reacquire the lock is another possible GUC. Again, I'm inclined to think that this could be hard-coded. Since autovacuum was knocked off-task after doing some significant work, I'm inclined to make this interval a little bigger, but I don't think it matters a whole lot. Anything between 20ms and 100ms seens sane. Maybe 50ms? At any point that it is unable to acquire the lock, there is a check for how long this autovacuum task has been starved for the lock. Initially I was arguing for twice the deadlock_timeout on the basis that this would probably be short enough not to leave the autovacuum worker sidelined for too long, but long enough for the attempt to get past a single deadlock between two other processes. This is the setting Jan is least willing to concede. If the autovacuum worker does abandon the attempt, it will keep retrying, since we go out of our way to prevent the autovacuum process from updating the statistics based on the "incomplete" processing. This last interval is not how long it will attempt to truncate, but how long it will keep one autovacuum worker making unsuccessful attempts to acquire the lock before it is put to other uses. Workers will keep coming back to this table until the truncate phase is completed, just as it does without the patch; the difference being that anytime it gets the lock, even briefly, it is able to persist some progress. So the question on the table is which of these three intervals should be GUCs, and what values to use if they aren't. -Kevin
-
Re: autovacuum truncate exclusive lock round two
Jan Wieck <janwieck@yahoo.com> — 2012-12-04T19:05:58Z
On 12/4/2012 1:51 PM, Kevin Grittner wrote: > Jan Wieck wrote: > >> [arguments for GUCs] > > This is getting confusing. I thought I had already conceded the > case for autovacuum_truncate_lock_try, and you appeared to spend > most of your post arguing for it anyway. I think. It's a little > hard to tell. Perhaps the best thing is to present the issue to the > list and solicit more opinions on what to do. Please correct me if > I mis-state any of this. > > The primary problem this patch is solving is that in some > workloads, autovacuum will repeatedly try to truncate the unused > pages at the end of a table, but will continually get canceled > after burning resources because another process wants to acquire a > lock on the table which conflicts with the one held by autovacuum. > This is handled by the deadlock checker, so another process must > block for the deadlock_timeout interval each time. All work done by > the truncate phase of autovacuum is lost on each interrupted > attempt. Statistical information is not updated, so another attempt > will trigger the next time autovacuum looks at whether to vacuum > the table. > > It's obvious that this pattern not only fails to release > potentially large amounts of unused space back to the OS, but the > headbanging can continue to consume significant resources and for > an extended period, and the repeated blocking for deadlock_timeout > could cause latency problems. > > The patch has the truncate work, which requires > AccessExclusiveLock, check at intervals for whether another process > is waiting on its lock. That interval is one of the timings we need > to determine, and for which a GUC was initially proposed. I think > that the check should be fast enough that doing it once every 20ms > as a hard-coded interval would be good enough. When it sees this > situation, it truncates the file for as far as it has managed to > get, releases its lock on the table, sleeps for an interval, and > then checks to see if the lock has become available again. > > How long it should sleep between tries to reacquire the lock is > another possible GUC. Again, I'm inclined to think that this could > be hard-coded. Since autovacuum was knocked off-task after doing > some significant work, I'm inclined to make this interval a little > bigger, but I don't think it matters a whole lot. Anything between > 20ms and 100ms seens sane. Maybe 50ms? > > At any point that it is unable to acquire the lock, there is a > check for how long this autovacuum task has been starved for the > lock. Initially I was arguing for twice the deadlock_timeout on the > basis that this would probably be short enough not to leave the > autovacuum worker sidelined for too long, but long enough for the > attempt to get past a single deadlock between two other processes. > This is the setting Jan is least willing to concede. > > If the autovacuum worker does abandon the attempt, it will keep > retrying, since we go out of our way to prevent the autovacuum > process from updating the statistics based on the "incomplete" > processing. This last interval is not how long it will attempt to > truncate, but how long it will keep one autovacuum worker making > unsuccessful attempts to acquire the lock before it is put to other > uses. Workers will keep coming back to this table until the > truncate phase is completed, just as it does without the patch; the > difference being that anytime it gets the lock, even briefly, it is > able to persist some progress. That is all correct. > > So the question on the table is which of these three intervals > should be GUCs, and what values to use if they aren't. I could live with all the above defaults, but would like to see more comments on them. Jan -- Anyone who trades liberty for security deserves neither liberty nor security. -- Benjamin Franklin
-
Re: autovacuum truncate exclusive lock round two
Robert Haas <robertmhaas@gmail.com> — 2012-12-05T15:07:41Z
On Tue, Dec 4, 2012 at 2:05 PM, Jan Wieck <JanWieck@yahoo.com> wrote: >> So the question on the table is which of these three intervals >> should be GUCs, and what values to use if they aren't. > > I could live with all the above defaults, but would like to see more > comments on them. I largely agree with what's already been said. The only interval that seems to me to maybe need its own knob is the total time after which the autovacuum worker will give up. If we set it to 2 * deadlock_timeout, some people might find that a reason to raise deadlock_timeout. Since people *already* raise deadlock_timeout to obscenely high values (a minute? an hour???) and then complain that things blow up in their face, I think there's a decent argument to be made that piggybacking anything else on that setting is unwise. Against that, FWICT, this problem only affects a small number of users: Jan is the only person I can ever remember reporting this issue. I'm not dumb enough to think he's the only person who it affects; but my current belief is that it's not an enormously common problem. So the main argument I can see against adding a GUC is that the problem is too marginal to justify a setting of its own. What I really see as the key issue is: suppose we hardcode this to say 2 seconds. Is that going to fix the problem effectively for 99% of the people who have this problem, or for 25% of the people who have this problem? In the former case, we probably don't need a GUC; in the latter case, we probably do. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company