MySQL刷脏,也是有个协调线程,通过不停的循环执行刷脏的任务,刷脏分为了2种类型,一种是刷lru,另一种是刷flush list.刷脏分为正常刷脏,sync flush和空闲刷脏,在正常刷脏和sync_flush 这两种是使用的同步刷,空闲刷使用的是异步刷,同步刷的情况忽略io_capacity的设置,空闲刷的方法是
buf_flush_lists(PCT_IO(100), LSN_MAX, &n_flushed); PCT_IO是受srv_io_capacity影响 这个函数会执行buf_flush_page,buf_flush_page是异步的,堆栈如下 mysqld!buf_flush_page(buf_pool_t*, buf_page_t*, buf_flush_t, bool) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:1145) mysqld!buf_flush_try_neighbors(page_id_t const&, buf_flush_t, unsigned long, unsigned long) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:1461) mysqld!buf_flush_page_and_try_neighbors(buf_page_t*, buf_flush_t, unsigned long, unsigned long*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:1533) mysqld!buf_do_flush_list_batch(buf_pool_t*, unsigned long, unsigned long long) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:1787) mysqld!buf_flush_batch(buf_pool_t*, buf_flush_t, unsigned long, unsigned long long) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:1866) mysqld!buf_flush_do_batch(buf_pool_t*, buf_flush_t, unsigned long, unsigned long long, unsigned long*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:2026) mysqld!buf_flush_lists(unsigned long, unsigned long long, unsigned long*) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:2132) mysqld!::buf_flush_page_cleaner_coordinator(void *) (/Users/xiaoyu.bai/Downloads/mysql-5.7.29/storage/innobase/buf/buf0flu.cc:3355) libsystem_pthread.dylib!_pthread_start (Unknown Source:0) libsystem_pthread.dylib!thread_start (Unknown Source:0)
sync flush的作用是控制,不要让脏页太久,如果lsn超过了lsn_limit+ 3倍的lsn_avg_rate就要执行同步刷脏。 正常刷脏是指有活动的情况,这种情况会计算出刷脏的数量,然后执行同步刷脏
n_to_flush = page_cleaner_flush_pages_recommendation( &lsn_limit, last_pages);
这里的同步是指,等待所有的刷新请求都已经被处理了,等待下面这个事件
os_event_wait(page_cleaner->is_finished);
不是刷最终的刷页是同步的,这里的刷页也是调用的buf_flush_page,异步的iopage cleaner worker线程
/******************************************************************//**
Worker thread of page_cleaner.
@return a dummy parameter */
extern "C"
os_thread_ret_t
DECLARE_THREAD(buf_flush_page_cleaner_worker)(
/*==========================================*/
void* arg MY_ATTRIBUTE((unused)))
/*!< in: a dummy parameter required by
os_thread_create */
{
my_thread_init();
mutex_enter(&page_cleaner->mutex);
page_cleaner->n_workers++;
mutex_exit(&page_cleaner->mutex);
#ifdef UNIV_LINUX
/* linux might be able to set different setting for each thread
worth to try to set high priority for page cleaner threads */
if (buf_flush_page_cleaner_set_priority(
buf_flush_page_cleaner_priority)) {
ib::info() << "page_cleaner worker priority: "
<< buf_flush_page_cleaner_priority;
}
#endif /* UNIV_LINUX */
while (true) {
os_event_wait(page_cleaner->is_requested);
ut_d(buf_flush_page_cleaner_disabled_loop());
if (!page_cleaner->is_running) {
break;
}
pc_flush_slot();
}
mutex_enter(&page_cleaner->mutex);
page_cleaner->n_workers--;
mutex_exit(&page_cleaner->mutex);
my_thread_end();
os_thread_exit();
OS_THREAD_DUMMY_RETURN;
}
在log buffer结构体中,有个属性,这个是控制同步刷的,使用同步io
lsn_t max_modified_age_sync; /*!< when this recommended value for lsn - buf_pool_get_oldest_modification() is exceeded, we start a synchronous preflush of pool pages */
在函数log_checkpoint_margin中,判断如果超过这个限制,会执行一个同步io的刷页
if (age > log->max_modified_age_sync) {
/* A flush is urgent: we have to do a synchronous preflush */
advance = age - log->max_modified_age_sync;
}
void
buf_flush_wait_flushed(
lsn_t new_oldest)
{
for (ulint i = 0; i < srv_buf_pool_instances; ++i) {
buf_pool_t* buf_pool;
lsn_t oldest;
buf_pool = buf_pool_from_array(i);
for (;;) {
/* We don't need to wait for fsync of the flushed
blocks, because anyway we need fsync to make chekpoint.
So, we don't need to wait for the batch end here. */
buf_flush_list_mutex_enter(buf_pool);
buf_page_t* bpage;
在for循环中注释说不用在此处等待fsync,不太明白为什么 有兴趣学习源码的加群一起学习啊 QQ: 700072075
