Innodb Read IO 相關參數源代碼解析

Innodb Read IO 相關參數源代碼解析

前言:最近在閱讀Innodb IO相關部分的源代碼。在閱讀之前一直有個疑問,show global status 中有兩個指標innodb_data_reads 和 innodb_data_read。兩個計數器僅差一個字母,他們之間的含義到底有何差別呢?本文將通過解析這兩個參數的含義,分析Innodb對於磁盤IO相關的一些知識

 首先我們來看下MySQL官方文檔裏對於這兩個參數的解釋:

 文檔對於這兩個參數的解釋非常曖昧。這裏的讀是指什麼?是從哪裏讀?磁盤還是內存?甚至連計數器的單位也不知道。

 

詳細解析:

接下來我們從源代碼來解析這兩個參數。在src/Srv0srv.c中存在對這兩個參數和代碼變量的映射關係的定義代碼,如下:

     export_vars.innodb_data_read = srv_data_read;
     export_vars.innodb_data_reads = os_n_file_reads; 

接着讓我們來看下這兩個代碼變量在哪裏進行了累加操作。

srv_data_read 盡有一處代碼進行累加操作,buf0file.c 的 _fil_io 函數中,操作如下:

  srv_data_read+= len;

從這行可以看出,innodb_data_read中實際存的是從磁盤上進行物理IO的字節數。

 

os_n_file_reads 也幾乎只有一處代碼進行累加(其他是windows的sync讀這裏忽略),在buf0file.c 的 中,操作如下:os_file_pread

  os_n_file_reads++;

隨後,代碼即調用os_aio_array_reserve_slot將IO請求推入 simulated array,再根據wake_later標誌位決定是否調用

os_aio_simulated_wake_handler_thread來立即喚醒IO工作隊列。從這裏也可以看到,innodb_data_reads記錄的是innodb對於磁盤發起的讀IO請求次數。

看到這裏我們就很容易產生一個疑問:既然兩個變量都是對磁盤發起的IO的計數器,爲什麼不直接放在一個函數的相鄰行裏呢?

回答這個問題,我們就需要對於innodb的simulated-aio和read-ahead算法有一定理解了。

進入到simulated的aio slot array的請求會有兩種,一種是通過buf_read_page 過來的普通頁的讀請求,一種是通過buf_read_ahead_random/linear 過來的預讀請求。從innodb的實現來說普通數據頁的請求是需要立即返回響應的,所以是同步(sync)IO。而對於預讀這樣數據並非SQL所需要,僅是用於提升性能的頁讀取,這樣的IO完全是可以異步的。這兩個差異也是導致simulated aio出現的原因。把IO請求推入slot array後,數據頁同步請求立即通知worker thread去os做同步IO。而預讀IO請求會不斷的推入slot array直到一次預讀所需要的page全部推入slot中,然後再會通知worker thread。此外在worker thread中,也會判斷一個segment的io請求是否相鄰連續,如果連續則把這些請求合併後,作爲一次OS IO發到下層存儲中。

明白了這些也就不難理解爲什麼計數器要分開在不同的函數中計數了。如果累加都放在 _fil_io中進行,那麼 innodb_data_read = 16K * innodb_data_reads (這裏假設page沒有做壓縮)。然而在有了異步IO合併這個操作後,實際的innodb_data_reads會少於_fil_io中獲得的計數次數。所以,通過 innodb_data_read / innodb_data_reads得到的比值也可以推斷出一個MySQL實例中順序IO或者可順序預讀的IO比例。

我們在production環境的服務器上做一個驗證:

服務器A:在線用戶訪問的數據庫,猜測隨機IO較多

SHOW GLOBAL STATUS LIKE '%innodb_data_read%';

Innodb_data_read 46384854470656
Innodb_data_reads 2812101578

每次IO平均讀取字節數=16494

服務器B:歷史數據統計的數據庫,數據內容和服務器A完全一樣,猜測順序IO較多

SHOW GLOBAL STATUS LIKE '%innodb_data_read%';

Innodb_data_read 54835669766144
Innodb_data_reads 2604758776

每次IO平均讀取字節數=21052

可見順序IO較多的MySQL的單次IO讀取字節數確實要多於一個page的大小,說明IO合併效果明顯。

而隨機IO較多的MySQL的單詞IO讀取字節數幾乎和一個page大小一致,即16K

 

https://www.cnblogs.com/cenalulu/archive/2013/10/16/3370626.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章