MySQL系列:innodb引擎分析之文件IO_MySQL
innodb作为数据库引擎,自然少不了对文件的操作,在innodb中所有需要持久化的信息都需要文件操作,例如:表文件、重做日志文件、事务日志文件、备份归档文件等。innodb对文件IO操作可以是煞费苦心,其主要包括两方面,一个是对异步io的实现,一个是对文件操作管理和io调度的实现。在MySQL-5.6版本的innodb还加入了DIRECT IO实现。做了这么多无非是优化io操作的性能。在innodb的文件IO部分中,主要实现集中在os_file.*和fil0fil.*两个系列的文件当中,其中os_file*是实现基本的文件操作、异步IO和模拟异步IO。fil0fil.*是对文件io做系统的管理和space结构化。下面依次来介绍这两个方面的内容.
1.系统文件IO
在innodb中,文件的操作是比较关键的,innodb封装了基本的文件操作,例如:文件打开与关闭、文件读写以及文件属性访问等。这些是基本的文件操作函数封装。在linux文件的读写方面,默认是采用pread/pwrite函数进行读写操作,如果系统部支持这两个函数,innodb用lseek和read、write函数联合使用来达到效果. 以下是innodb文件操作函数: os_file_create_simple 创建或者打开一个文件 os_file_create 创建或者打开一个文件,如果操作失败会重试,直到成功 os_file_close 关闭打开的文件 os_file_get_size 获得文件的大小 os_file_set_size 设置文件的大小并以0填充文件内容 os_file_flush 将写的内容fsync到磁盘 os_file_read 从文件中读取数据 os_file_write 将数据写入文件 innodb除了实现以上基本的操作以外,还实现了文件的异步IO模型,在Windows下采用的IOCP模型来进行处理(具 体可以见网上的资料),在linux下是采用aio来实现的,有种情况,一种是通过系统本身的aio机制来实现,还有一种是 通过多线程信号模拟来实现aio.这里我们重点来介绍,为了实现aio,innodb定义了slot和slot array,具体数据结构如下:typedef struct os_aio_slot_struct { ibool is_read; /*是否是读操作*/ ulint pos; /*slot array的索引位置*/ ibool reserved; /*这个slot是否被占用了*/ ulint len; /*读写的块长度*/ byte* buf; /*需要操作的数据缓冲区*/ ulint type; /*操作类型:OS_FILE_READ OS_FILE_WRITE*/ ulint offset; /*当前操作文件偏移位置,低32位*/ ulint offset_high; /*当前操作文件偏移位置,高32位*/ os_file_t file; /*文件句柄*/ char* name; /*文件名*/ ibool io_already_done; /*在模拟aio的模式下使用,TODO*/ void* message1; void* message2; #ifdef POSIX_ASYNC_IO struct aiocb control; /*posix 控制块*/ #endif }os_aio_slot_t; typedef struct os_aio_array_struct { os_mutex_t mutex; /*slots array的互斥锁*/ os_event_t not_full; /*可以插入数据的信号,一般在slot数据被aio操作后array_slot有空闲可利用的slot时发送*/ os_event_t is_empty; /*array 被清空的信号,一般在slot数据被aio操作后array_slot里面没有slot时发送这个信号*/ ulint n_slots; /*slots总体单元个数*/ ulint n_segments; /*segment个数,一般一个对应n个slot,n = n_slots/n_segments,一个segment作为aio一次的操作范围*/ ulint n_reserved; /*有效的slots个数*/ os_aio_slot_t* slots; /*slots数组*/ os_event_t* events; /*slots event array,暂时没弄明白做啥用的*/ }os_aio_array_t;

2.文件管理的内存结构
在innodb中定义三种文件类型:表空间文件(ibdata*)、重做日志文件(ib_logfile*)和归档文件(ib_arch_log*)。一般innodb在运行的过程中,会同时打开很多个文件,这就要求对文件进行系统的管理和控制。在innodb中定义了一套基于fil_system_t、fil_space_t和fil_node_t的内存管理结构。每个文件对应的是一个fil_node_t,fil_node是存储的最小单元,多个同一模块的fil_node组成一个fil_space_t,所有的space组成一个fil_system_t,在innodb引擎里,只有一个fil_system_t对象。
fil_system_t管理着全局的文件操作资源,例如:文件打开的数量、打开文件的信号控制、fil_space_t的管理和索引等。以下是fil_system_t的结构定义:
typedef struct fil_system_struct { mutex_t mutex; /*file system的保护锁*/ hash_table_t* spaces; /*space的哈希表,用于快速检索space,一般是通过space id查找*/ ulint n_open_pending; /*当前有读写IO操作的fil_node个数*/ ulint max_n_open; /*最大允许打开的文件个数*/ os_event_t can_open; /*可以打开新的文件的信号*/ UT_LIST_BASE_NODE_T(fil_node_t) LRU; /*最近被打开操作过的文件,用于快速定位关闭的fil_node*/ UT_LIST_BASE_NODE_T(fil_node_t) space_list; /*file space的对象列表*/ }fil_system_t;
fil_space_t是用于管理同一模块的file_node,上层模块操作文件不是以文件名来做操作关联的,而是用space_id,
也就是说,所有的文件操作是通过space为单位进行操作的。fil_space支持三种类型,分别是:
FIL_TABLESPACE 表空间space
FIL_LOG 重做日志space
FIL_ARCHI_LOG 归档日志space
fil_space_t的定义如下:
struct fil_space_struct { char* name; /*space名称*/ ulint id; /*space id*/ ulint purpose; /*space的类型,主要有space table, log file和arch file*/ ulint size; /*space包含的页个数*/ ulint n_reserved_extents; /*预留的页个数*/ hash_node_t hash; /*chain node的HASH表*/ rw_lock_t latch; /*space操作保护锁,用于多线程并发*/ ibuf_data_t* ibuf_data; /*space 对应的insert buffer*/ ulint magic_n; /*魔法校验字*/ UT_LIST_BASE_NODE_T(fil_node_t) chain; UT_LIST_NODE_T(fil_space_t) space_list; };
fil_space_create 创建一个fil_space
fil_space_free 销毁一个fil_space
fil_space_truncate_start 从space中删除fil_node,删除的总数据长度为trunc_len
fil_node_create 创建一个fil_node并加入到对应的space当中
fil_space_get_size 获得space的空间大小,以page为单位记
fil_io 指定space的io操作
fil_aio_wait aio异步方式的io操作等待,并根据完成状态更新space状态
fil_flush 指定space进行数据刷盘
fil_node_t是对单个文件进行管理,主要是管理文件的打开状态、文件句柄信息、文件的page数量和更新状态等。
其结构定义如下:
struct fil_node_struct { char* name; /*文件路径名*/ ibool open; /*文件是否被打开*/ os_file_t handle; /*文件句柄*/ ulint size; /*文件包含的页个数,一个页是16K*/ ulint n_pending; /*等待读写IO操作的个数*/ ibool is_modified; /*是否有脏也存在,flush是根据这个标志进行刷盘的*/ ulint magic_n; /*魔法校验字*/ UT_LIST_NODE_T(fil_node_t) chain; UT_LIST_NODE_T(fil_node_t) LRU; };
值得注意的是当外部调用了fil_flush时,判断一个fil_node是否需要刷盘的必要条件是:
文件必须是打开的 open = TRUE
文件存在内存和硬盘数据不一致 is_modified = TRUE
了解了他们三者的基本定义后,那他们之间的关系是怎么的?不用文字叙述,看下面的内存结构关系图:
在了解了他们之间的基本关系后,那么一个io操作是怎么进行的?在这个模型里,一个io操作提交和被运行是比较复杂的。具体流程如下: 1.外部模块提交一个fil_io, 先会进行基本的io操作类型的判断和文件打开方式的判断。 2.然后进行对正在进行io操作的计数做判断,如果正在进行的io数量 > 最大文件打开数量的四分之三,唤醒所有aio的操作线程进行io处理,并进行sleep等待。 3.如果正在进行的io数量 = 最大文件打开数量,唤醒所有的aio操作线程进行io处理,并等待fil_system_t的can_open信号。 4.如果不满足2和3,找到需要受理io操作的space和node,并打开node对应的文件,打开文件时会对打开文件数量限制做判断,如果当前打开文件操作io的数量 + LRU里已经打开文件的数量>= 最大文件打开数量时,会取出LRU中最后一个fil_node进行文件关闭。然后在对新的io操作的fil_node文件进行打开。 5.fil_node文件打开后,调用os_aio进行io操作提交,然后等待io操作完成 6. io操作完成后,将完成io操作的fil_node放入LRU的第一个位置,并更改对应的fil_system/fil_space/fil_node的状态,最后触发一个fil_system的can open信号。 7.监听can_open的线程收到这个信号后,会跳到第4步进行自己的io操作提交。 流程图如下:

3总结
总体来说,innodb的文件IO涉及到知识面很多,可以能短时间无法完全理解透彻,一般在阅读源码的时候可以做一些基本的单元测试,这样有助于理解。弄清楚innodb的文件IO操作是非常有必要的,因为文件IO操作模块直接影响对innodb的日志系统的理解、表空间系统的理解。而且Innodb在文件IO模块的改进还是比较大的,尤其是引入Direct IO后。Direct IO很多数据库都在用这个技术,除了innodb,oracle和淘宝的oceanbase都使用了这个技术, 关于Direct IO网络上资料很多,可以自行结合MySQL-5.6的innodb来做研究。
熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

開啟微信,在我中選擇設置,選擇通用後選擇儲存空間,在儲存空間選擇管理,選擇要恢復檔案的對話選擇感嘆號圖示。教學適用型號:iPhone13系統:iOS15.3版本:微信8.0.24解析1先開啟微信,在我的頁面中點選設定選項。 2接著在設定頁面中找到並點選通用選項。 3然後在通用頁面中點選儲存空間。 4接下來在儲存空間頁面中點選管理。 5最後選擇要恢復檔案的對話,點選右側的感嘆號圖示。補充:微信文件一般幾天過期1要是微信接收的文件並沒有點開過的情況下,那在七十二鐘頭之後微信系統會清除掉,要是己經查看了微信

在Windows系統中,照片應用程式是一個方便的方式來檢視和管理照片和影片。透過這個應用程序,用戶可以輕鬆存取他們的多媒體文件,而無需安裝額外的軟體。然而,有時用戶可能會碰到一些問題,例如在使用照片應用程式時遇到「無法開啟此文件,因為不支援該格式」的錯誤提示,或在嘗試開啟照片或影片時出現文件損壞的問題。這種情況可能會讓使用者感到困惑和不便,需要進行一些調查和修復來解決這些問題。當用戶嘗試在Photos應用程式上開啟照片或影片時,會看到以下錯誤。抱歉,照片無法開啟此文件,因為目前不支援該格式,或該文件

在本文中,我們將介紹如何解決在Windows系統中刪除檔案或資料夾時出現「準備刪除」提示的問題。這個提示意味著系統正在進行一些背景操作,例如檢查檔案權限、驗證檔案是否被其他程式佔用、計算要刪除項目的大小等。我們將為您提供一些解決方法,以確保您能夠順利刪除文件,而無需等待太長時間。為什麼Windows要花這麼長時間才能刪除檔案? Windows準備刪除檔案所需的時間受多種因素影響,包括檔案大小、儲存裝置速度和後台進程。長時間或被卡住的「正在準備刪除」提示可能暗示系統資源不足、磁碟錯誤或檔案系統問題。在

gho檔案是一種GhostImage影像文件,它通常用於將整個硬碟或分割區的資料備份成一個檔案。在一些特定的情況下,我們需要將這種gho檔案重新安裝回硬碟上,以還原硬碟或分割區到先前的狀態。下面將介紹gho檔案的安裝方法。首先,在安裝之前,我們需要準備以下工具和材料:實體的gho文件:確保你擁有一份完整的gho文件,它通常以.gho為後綴名,並且包含有備份

Tmp格式檔案是一種暫存檔案格式,通常由電腦系統或程式在執行過程中產生。這些文件的目的是儲存臨時數據,以幫助程式正常運行或提高效能。一旦程式執行完成或電腦重啟,這些tmp檔案往往就沒有了存在的必要性。所以,對於Tmp格式檔案來說,它們本質上是可以刪除的。而且,刪除這些tmp檔案能夠釋放硬碟空間,確保電腦的正常運作。但是,在刪除Tmp格式檔案之前,我們需

在電腦中刪除或解壓縮資料夾,時有時會彈出提示對話框“錯誤0x80004005:未指定錯誤”,如果遇到這中情況應該怎麼解決呢?提示錯誤碼0x80004005的原因其實很多,但大部分因為病毒導致,我們可以重新註冊dll來解決問題,下面,小編給大夥講解0x80004005錯誤代碼處理經驗。有使用者在使用電腦時出現錯誤代碼0X80004005的提示,0x80004005錯誤主要是由於電腦沒有正確註冊某些動態連結庫文件,或電腦與Internet之間存在不允許的HTTPS連接防火牆所引起。那麼如何

檔案路徑是作業系統中用於識別和定位檔案或資料夾的字串。在檔案路徑中,常見的有兩種符號分隔路徑,即正斜線(/)和反斜線()。這兩個符號在不同的作業系統中有不同的使用方式和意義。正斜線(/)是Unix和Linux系統中常用的路徑分隔符號。在這些系統中,檔案路徑是以根目錄(/)為起始點,每個目錄之間使用正斜線進行分隔。例如,路徑/home/user/Docume

夸克網盤和百度網盤都是現在最常用的儲存文件的網盤軟體,如果想要將夸克網盤內的文件保存到百度網盤,要怎麼操作呢?本期小編整理了夸克網盤電腦端的檔案轉移到百度網盤的教學步驟,一起來看看是怎麼操作吧。 夸克網盤的檔案怎麼存到百度網盤?要將夸克網盤的文件轉移到百度網盤,首先需在夸克網盤下載所需文件,然後在百度網盤用戶端中選擇目標資料夾並開啟。接著,將夸克網盤中下載的檔案拖放到百度網盤用戶端開啟的資料夾中,或使用上傳功能將檔案新增至百度網盤。確保上傳完成後在百度網盤中查看檔案是否已成功轉移。這樣就
