innodb學習筆記(一) aio的使用
innodb學習筆記(一) aio的使用
這裡先以mysql 5.7.26版本進行學習。
一. 四種IO執行緒及執行緒數量
分為讀執行緒,寫執行緒,log io執行緒和buf io執行緒,重點在innobase/os/Osofile.cc這個檔案裡。
1.1 aio讀寫執行緒
innodb可以配置aio執行緒的數量,在圖1-1某線上例項的my.cnf中可以看到讀執行緒和寫執行緒數量的配置,這裡一例讀寫執行緒數量各自為8。後文都以讀8寫8為例說明。
圖 1-1 某線上例項執行緒數量配置
實際程式碼中srv0start.cc負責aio的初始化,這裡實際對應srv_n_read_io_threads和srv_n_write_io_threads兩個引數分別指定負責讀IO的執行緒數量和負責寫IO的執行緒數量;
當然除了指定的讀執行緒和寫執行緒外,還有一個log io thread和ibuf io thread。所以實際的io執行緒總數srv_n_file_io_threads就是:
srv_n_file_io_threads = srv_n_read_io_threads + srv_n_write_io_threads + 2
以上這些邏輯在innobase_start_or_create_for_mysql()初始化中可以看到。
綜上,一個mysql例項中有:
- 4種不同的IO執行緒;
- n個read io執行緒,n個write io執行緒,一個log io執行緒,一個buf io執行緒;
二. aio管理結構
核心是定義在os0file.cc中的class AIO結構,如下圖列出了其中所有的類成員和部分重要類方法。
圖 2-1 aio類
其實全域性來看AIO結構是一個工廠,並不會有實體,該工廠可以根據引數分別建立read io,write io,log io和ibuf io這四種不同的AIO例項,這些例項被建立好後賦給相應的static AIO *指標,之後在db例項的整個執行過程中就可以通過諸如s_reads, s_writes這樣的static指標來呼叫相應的AIO例項。
2.1 AIO結構中重要的成員
- m_mutex
對於wirte和read型別的AIO,會有多個執行緒來操作AIO例項,因此需要mutex進行互斥;
- m_slots
一個AIO包含的所有的slot例項,儲存在該向量中,每個slot代表一個io請求,可能是讀,也可能是寫。slot的數量為相應的執行緒數量 n 乘以系統規定的該類執行緒允許的pending aio的數量,其中執行緒數量n在上一節已經給出,而該類執行緒允許pending aio的數量為硬編碼n * OS_AIO_N_PENDING_IOS_PER_THREAD為256;
對於read/write io型別的AIO,slot數量為執行緒數n * 256,這些slot需要均分成m_n_segments份,其實m_n_segments就是執行緒數量;
- m_n_segments
所有的slot會被分隔成m_n_segments份,其實就是io執行緒數量,一個io執行緒可以以io_getevents等待在任一segment上,其實一個segment就對應一個io_ctx;可以推斷,針對某一種io執行緒,比如write io數量為8,那麼m_n_segments值就為8,slots被分隔成8個segment,每個segment包含的slot數量為256;從後續程式碼可以看到,每個io_ctx在被io_setup和io getevents時,引數nr和max_nr都為256;
圖 2-2 slot的分割
實際上看起來分成多個segments的主要目的除了提前分配好m_n_segments個io_ctx外,可以把實體地址相近的io放入到同一segments中方便可能存在的io merge,如reserve_slot()中所示;
但是,reserve_slot()中選擇了一個segment後,io並不一定真的能放入這個segment中,只是從這個segment開始搜尋第一個未被佔用的slot而已;
- m_not_full
條件變數,噹噹前AIO的slots從full變成not full時就釋放這個條件變數,表示有空餘的slot可以用來提交io請求了,如reserve_slot()中所示;
- m_is_empty
條件變數,噹噹前AIO的被reserved的slot數量從0變成1時該條件會被hold,見reserve_slot();當reserved的slot數量從1變成0時會被釋放,見AIO::release();
從程式碼來看,只有s_write型別的AIO會存在對該條件變數的wait,主要是log file和db wirte file的flush的前置操作;
- m_n_reserved
該AIO中被佔用的slot總數,維護這個數字主要是做為m_not_full和m_is_empty兩個條件變數操作的依據;
- m_aio_ctx
n_segments個aio上下文組成的陣列,正好每個IO執行緒對應一個;
- m_events
n_slots個aio_event組成的陣列,aio event完成後,io_getevents將io_event儲存的位置;
- s_log/s_writes/s_reads/s_ibuf
四種不同型別io執行緒對應的AIO例項;
2.2 Slot結構
一個Slot結構代表一個io請求。Slot結構非常容易理解,該IO相關的一些資訊。
圖 2-3 slot結構
三. AIO初始化
aio的初始化從os_aio_init,可以分為兩個範疇:
- AIO範疇:分別為各種io型別建立AIO例項,也就是呼叫AIO::create()函式,對於每個AIO例項,就是執行建構函式和init成員方法;
- linux aio範疇:對於每一個AIO例項內部,io_setup準備m_n_segment個aio_ctx,也就是每個io執行緒對應一個;每個aio_ctx的max_event值為該AIO的m_slots.size()除以m_n_segment,其實就是256;這些操作是在init_linux_native_aio()中完成;
以上兩個操作還包含了為AIO例項以及Slot例項的成員變數賦初始值。
圖 3-1 aio初始化函式呼叫
四. AIO執行緒邏輯
在程式碼中多處看到諸如# ifdef UNIV_PFS_THREAD這樣的巨集,這裡pfs是指performance schema instrumented,這是用於監控MySQL server在一個較低階別的執行過程中的資源消耗、資源等待等情況的一個模組,參考https://blog.csdn.net/qq_35068291/article/details/105921515。
AIO邏輯當然包括提交IO請求(submit)和IO收割(getevents)兩部分,實際上innodb裡的AIO邏輯主要是在收割上,前文所述的IO執行緒都是在做收割工作,所以我們先來看下收割邏輯。
4.1 收割
AIO執行緒主函式是io_handler_thread,在innobase_start_or_create_for_mysql( )中可以看到create了srv_n_file_io_threads個AIO執行緒均是以io_handler_thread為執行緒主函式。
圖 4-1 aio收割邏輯
如圖4-1所示,其實主函式就是不斷迴圈呼叫fil_aio_wait函式,fil_aio_wait則負責實際的對segment中aio_ctx的io_getevents和善後工作。
其中os_aio_handler是實際的收割動作,segment實際指定了aio_ctx,其他引數其實都是輸出型結果引數。
4.2 提交
linux_dispatch通過io_submit提交aio,層層回推,aio的submit入口是fil_io函式。
fil_io一個主要的使用場景是刷髒頁,邏輯比較複雜,準備後面專門分析,這裡畫了一個主要的邏輯圖。
https://www.processon.com/view/link/5f6602cee401fd2ad7eb852
相關文章
- MySQL:Innodb恢復的學習筆記MySql筆記
- InnoDB文件筆記(一)筆記
- 學習筆記(一)筆記
- 《MySQL實戰45講》學習筆記4——MySQL中InnoDB的索引MySql筆記索引
- numpy的學習筆記\pandas學習筆記筆記
- java BIO/NIO/AIO 學習JavaAI
- kitten 學習教程(一) 學習筆記筆記
- TS學習筆記(一)筆記
- unity學習筆記(一)Unity筆記
- oracle學習筆記《一》Oracle筆記
- ANFIS學習筆記(一)筆記
- Selenium 學習筆記 (一)筆記
- Kettle學習筆記(一)筆記
- Spring學習筆記(一)Spring筆記
- Matlab學習筆記(一)Matlab筆記
- opencv學習筆記(一)OpenCV筆記
- LaTeX學習筆記:一筆記
- GOLang 學習筆記(一)Golang筆記
- SpringMVC學習筆記(一)SpringMVC筆記
- Cesium學習筆記(一)筆記
- kafka學習筆記(一)Kafka筆記
- Angular 學習筆記(一)Angular筆記
- React 學習筆記【一】React筆記
- vue學習筆記一Vue筆記
- Canvas學習筆記(一)Canvas筆記
- Python 學習筆記(一)Python筆記
- Jquery學習筆記(一)jQuery筆記
- goLang學習筆記(一)Golang筆記
- Android學習筆記一Android筆記
- css學習筆記(一)CSS筆記
- SCSS學習筆記(一)CSS筆記
- 深度學習 筆記一深度學習筆記
- InnoDB學習(一)之BufferPool
- Vue學習筆記之Webpack的使用Vue筆記Web
- Beautiful Soup庫的使用(學習筆記)筆記
- Egg 學習筆記 - 外掛的使用筆記
- 【學習筆記】Go Modules 使用筆記Go
- webpack 學習筆記:使用 lodashWeb筆記