MySQL刷髒

aoerqileng發表於2022-09-04

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,非同步的io

page 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

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25719946/viewspace-2913358/,如需轉載,請註明出處,否則將追究法律責任。

相關文章