這篇文章運用簡單易懂的例子給大家介紹詳解Mysql臟頁flush及收縮表空間的原理,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
mysql臟頁
由于WAL機制,InnoDB在更新語句的時候,制作了寫日志這一個磁盤操作,就是redo log,在內存寫完redo log后,就返回給客戶端, 即更新成功。
把內存里的數據寫入磁盤的過程,術語就是flush,在flush之前,實際數據和數據庫中的數據是不一致的,因為在redo log基礎上更新了還未寫入,數據庫是老的,當內存數據頁跟磁盤數據頁內容不一致的時候,稱這個內存頁為臟頁,內存寫入后就一致了,稱為干凈頁,
如果mysql偶爾運行速度很慢,很可能是在刷臟頁。引發數據庫flush的過程
所以我們有時使用數據庫會發現數據庫性能突然下降,可能就是在處理臟頁。
刷臟頁控制策略
場景例子:數據庫占用空間太大,把最大的表刪掉了一半數據,表的大小還是沒有變化。
數據刪除流程

加入要刪掉R4,InnoDB引擎只會把R4這個記錄標記為刪除,如果之后再摻入一個ID在300-600之間的記錄時,會復用這個位置,但是磁盤文件的大小并不會縮小。
如果刪掉了一個數據頁上的所有記錄,這個數據頁就可以被復用。
注意:數據頁的復用跟記錄的復用是不同的。
插入數據流程
如果數據按照索引順序插入的,索引是緊湊的,但是如果是隨機插入的,就會造成索引的數據頁分頁。

如果pageA已經滿了,在插入一行數據會怎樣?由于A滿了,在插入一個id是550的數據時,就會申請一個新的頁面pageB來保存數據,分裂完成后pageA的末尾就留下了空洞。
更新索引上的值也是刪除一個舊的值,再插入一個新值,也會造成空洞。
收縮空間
新建一個與表A相同結構的表B,按照主鍵ID遞增的順序,把數據一行一行的從A里讀出來再插入到表B中,表B中無空洞,數據頁的利用率也更高,如果我們把表B作為臨時表,數據從表A導入到B中的操作完成后,用B替換A,從效果上也起到了收縮A的作用。

在整個DDL過程中,表A不能有更新,所以這個DDL不是online的,在5.6之后的版本中,流程做了更改:
建立一個臨時文件,掃描A中的所有數據頁,
用數據頁中A的記錄生成B+樹,存儲在臨時文件中
將所有對A的操作記錄在一個日志文件中
臨時文件生成后,將日志文件的操作應用到臨時文件,得到一個邏輯數據上與表A相同的數據文件
用臨時文件替換表A的數據文件
圖示

可以看到,與圖3過程的不同之處在于,由于日志文件記錄和重放操作這個功能的存在,這個方案在重建表的過程中,允許對表A做增刪改操作。
使用alter table A engine=InnoDB命令來重建表。在MySQL 5.5版本之前,這個命令的執行流程跟我們前面描述的差不多,區別只是這個臨時表B不需要你自己創建,MySQL會自動完成轉存數據、交換表名、刪除舊表的操作。
關于詳解Mysql臟頁flush及收縮表空間的原理就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。