WL#5579: Add 'page_cleaner' a separate thread to flush dirty pages
Status: Complete
In Trondheim we decided that it makes sense to move the flushing activity in innodb to a separate thread. Currently flushing activity happens in either the master thread or in the user threads. There are two types of flushing activities i.e.: flush_list and LRU_list. More details about this can be found in the following presentation: https://inside.mysql.com/mywiki/images/f/fe/InnoDB_flushing.odp This WL will trace the following activities: * Have a separate thread for flushing. We'll call it page_cleaner. No strict opinion on name. If you have something better I'll change it. * Move the flushing of dirty pages from the master thread to the page_cleaner * Move the flushing when log->max_modified_age_async is reached to the page_cleaner. The following won't be touched by this WL: * Flushing that happens in the user thread when log->max_modified_age_sync is reached. * LRU flushing (WL#5580) * After tweaking with adaptive flushing heuristics I have realized that it is better left as a separate piece of work. The scope of this WL is now to have a page_cleaner thread and move async flushing to the background. WL#5666 is for adaptive flushing. Changes in innodb status output: ================================ fprintf(file, "Log sequence number %llu\n" "Log flushed up to %llu\n" + "Pages flushed up to %llu\n" "Last checkpoint at %llu\n", log_sys->lsn, log_sys->flushed_to_disk_lsn, + log_buf_pool_get_oldest_modification(), log_sys->last_checkpoint_lsn); - fprintf(file, "srv_master_thread loops: %lu 1_second, %lu sleeps, " - "%lu 10_second, %lu background, %lu flush\n", - srv_main_1_second_loops, srv_main_sleeps, - srv_main_10_second_loops, srv_main_background_loops, - srv_main_flush_loops); + fprintf(file, "srv_master_thread loops: %lu srv_active, " + "%lu srv_shutdown, %lu srv_idle\n", + srv_main_active_loops, + srv_main_shutdown_loops, + srv_main_idle_loops);
We'll have a separate page_cleaner thread.
- As a first cut I'll have a single page_cleaner. Eventually we can move to have
multiple such threads.
- For now I'll not use the SRV_WORKER thread mechanism to dispatch discreet
tasks to the page_cleaner. Sunny's MT purge has the basic infrastructure to use
multiple worker threads. We can port this patch to eventually use that once MT
purge makes it to the trunk.
page_cleaner tasks:
===================
- flushing of dirty pages based on:
* max_dirty_ratio
* adaptive_flushing heuristic
* async preflushing when nearing checkpoint age
- flushing of dirty pages in periods of inactivity
- flushing of dirty pages at shutdown
What page_cleaner will not do (still remain with master or other threads)
=========================================================================
- Syncing of log buffer every second
- making checkpoints
- ibuf merge
- purge
page_cleaner and LRU flushing:
==============================
This WL won't touch LRU flushing. Eventually LRU flushing will be moved to the
page_cleaner as well. At that point we may opt to have multiple page_cleaner if
required.
Startup/Shutdown:
=================
- page_cleaner will be spawned after IO threads and before any other threads
during the server startup
- page_cleaner will exit after all other threads (including purge thread/s) have
exited and before master thread has exited (maybe we can allow master thread to
exit before page_cleaner and only need IO helper threads to alive and kicking).
polling or signalling:
======================
We have a choice to either have the master thread (or other user threads) signal
the page_cleaner that some work is needed or else we can use polling.
For the sake of simplicity I'd start with polling mechanism which is closer to
what master thread has been doing i.e.: doing one second loops and ten seconds
loops.
Note that page_cleaner will have to eventually wait on some event when there is
no activity at all. And that suspension will end with a signal. But generally
the page_cleaner will check state of the system itself to decide how much work
to do and when to do it.
page_cleaner activities:
========================
while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
sleep if needed;
if(srv_active)
if(async_flushing_needed)
do async_flushing
if(max_dirty_ratio_reached)
do max_dirty_flushing
if(adaptive_flushing_needed)
do adaptive_flushing
else
do idle_flushing
while(other threads active)
keep doing shutdown_flushing
exit
REF: rb://481
Copyright (c) 2000, 2025, Oracle Corporation and/or its affiliates. All rights reserved.