1. 程式人生 > 資料庫 >Mysql髒頁flush及收縮表空間原理解析

Mysql髒頁flush及收縮表空間原理解析

mysql髒頁

由於WAL機制,InnoDB在更新語句的時候,製作了寫日誌這一個磁碟操作,就是redo log,在記憶體寫完redo log後,就返回給客戶端, 即更新成功。

把記憶體裡的資料寫入磁碟的過程,術語就是flush,在flush之前,實際資料和資料庫中的資料是不一致的,因為在redo log基礎上更新了還未寫入,資料庫是老的,當記憶體資料頁跟磁碟資料頁內容不一致的時候,稱這個記憶體頁為髒頁,記憶體寫入後就一致了,稱為乾淨頁,

如果mysql偶爾執行速度很慢,很可能是在刷髒頁。引發資料庫flush的過程

  • redo log滿了,系統停止所有更新操作,將checkpoint向前推進,騰出空間繼續寫。
  • 系統記憶體不足,需要新的記憶體頁不夠用,就會淘汰一些資料頁,留給別的資料頁使用,如果淘汰的是髒頁,就會先寫到磁碟。
  • mysql空閒的時候。
  • 正常關閉mysql的時候
  • 在第一種情況下,redo log滿了,這種情況是innodb要避免的,因為整個系統都不能再更新了,這是不能接受的
  • 第二種情況,記憶體滿了,要先寫到磁碟,innodb用緩衝池管理記憶體,有三種狀態
  • 還沒有用的記憶體頁
  • 用了並且是乾淨頁
  • 用了並且是髒頁(淘汰的時候需要寫入到磁碟)

所以我們有時使用資料庫會發現資料庫效能突然下降,可能就是在處理髒頁。

刷髒頁控制策略

  • Innodb_io_capacity引數,這個引數會告訴innodb你的磁碟io能力。(有公式計算)
  • innodb刷盤主要兩個因素:髒頁比例和redo log的寫盤速度
  • innodb_max_derty_pages_pct是髒頁比例上限,預設是75%,調整好Innodb_io_capacity引數值,使髒頁比例不要超過75%收縮表空間

場景例子:資料庫佔用空間太大,把最大的表刪掉了一半資料,表的大小還是沒有變化。

資料刪除流程

Mysql髒頁flush及收縮表空間原理解析

加入要刪掉R4,InnoDB引擎只會把R4這個記錄標記為刪除,如果之後再摻入一個ID在300-600之間的記錄時,會複用這個位置,但是磁碟檔案的大小並不會縮小。

如果刪掉了一個數據頁上的所有記錄,這個資料頁就可以被複用。

注意:資料頁的複用跟記錄的複用是不同的。

  • 比如R4這條記錄被刪除,如果插入一個ID是400的行,直接複用這個空間,但是如果插入ID是800的行,就不能複用這個位置了。
  • 但是整個資料頁Page A上的所有記錄刪除之後,pageA標記為可複用,如果插入一條ID=50的記錄需要用新的資料頁的時候,PageA是可以揹負用的。
  • 如果我們用delete命令把整個表資料刪除,結果是所有的資料頁都會標記為可複用,但是在磁碟上,檔案不會變小。

插入資料流程

如果資料按照索引順序插入的,索引是緊湊的,但是如果是隨機插入的,就會造成索引的資料頁分頁。

Mysql髒頁flush及收縮表空間原理解析

如果pageA已經滿了,在插入一行資料會怎樣?由於A滿了,在插入一個id是550的資料時,就會申請一個新的頁面pageB來儲存資料,分裂完成後pageA的末尾就留下了空洞。

更新索引上的值也是刪除一箇舊的值,再插入一個新值,也會造成空洞。

收縮空間

新建一個與表A相同結構的表B,按照主鍵ID遞增的順序,把資料一行一行的從A裡讀出來再插入到表B中,表B中無空洞,資料頁的利用率也更高,如果我們把表B作為臨時表,資料從表A匯入到B中的操作完成後,用B替換A,從效果上也起到了收縮A的作用。

Mysql髒頁flush及收縮表空間原理解析

在整個DDL過程中,表A不能有更新,所以這個DDL不是online的,在5.6之後的版本中,流程做了更改:

建立一個臨時檔案,掃描A中的所有資料頁,

用資料頁中A的記錄生成B+樹,儲存在臨時檔案中

將所有對A的操作記錄在一個日誌檔案中

臨時檔案生成後,將日誌檔案的操作應用到臨時檔案,得到一個邏輯資料上與表A相同的資料檔案

用臨時檔案替換表A的資料檔案

圖示

Mysql髒頁flush及收縮表空間原理解析

可以看到,與圖3過程的不同之處在於,由於日誌檔案記錄和重放操作這個功能的存在,這個方案在重建表的過程中,允許對錶A做增刪改操作。

使用alter table A engine=InnoDB命令來重建表。在MySQL 5.5版本之前,這個命令的執行流程跟我們前面描述的差不多,區別只是這個臨時表B不需要你自己建立,MySQL會自動完成轉存資料、交換表名、刪除舊錶的操作。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。