你插入MySQL的數據真的存到表裏了麼?

現在有這麼一個問題:當你執行一條insert語句之後,插入的數據就已經保存在磁盤中了麼?

答案是不一定 ,那是爲什麼呢?首先來了解一下MySQL在InnoDB存儲引擎中,數據是怎麼存儲的。

1. InnoDB數據存儲單元

同大多數數據庫一樣,InnoDB有頁(Page)的概念(也可以稱爲塊),頁是InnoDB磁盤管理的最小單位。在InnoDB存儲引擎中,默認每個頁的大小爲16 KB。而從InnoDB 1.2.x版本開始,可以通過參數InnoDB_page_size將頁的大小設置爲4 K、8 K、16 K。若設置完成,則所有表中頁的大小都爲InnoDB_page_size,不可以對其再次進行修改。除非通過mysqldump導入和導出操作來產生新的庫。
在這裏插入圖片描述

InnoDB的數據是按數據頁爲單位來讀寫的。也就是說,當需要讀一條記錄的時候,並不是將這個記錄本身從磁盤讀出來,而是以頁爲單位,將其整體讀入內存。

而將數據從磁盤讀入內存涉及隨機IO的訪問,是數據庫裏面成本最高的操作之一,所以爲了減少磁盤IO,InnoDB設計了change buffer這個機制。

2. change buffer

在MySQL 5.5之前的版本中,由於只支持緩存insert操作,所以最初叫做insert buffer,只是後來的版本中支持了更多的操作類型緩存,才改叫change buffer,這也是爲什麼代碼中有大量的ibuf前綴開頭的函數或變量。

然而使用change buffer需要同時滿足兩個條件:

(1) 索引是輔助索引

插入聚簇索引一般是順序的,一般不需要磁盤的隨機讀取,所以不需要使用change buffer

(2) 索引不是唯一的

輔助索引不能是唯一的,因爲在插入緩衝時,數據庫並不去查找索引頁來判斷插入的記錄的唯一性。如果去查找肯定又會有離散讀取的情況發生,從而導致change buffer失去了意義。

3. change buffer的底層實現

change buffer底層結構是一顆全局的B+樹,負責對所有的表空間進行change buffer。

4. merge buffer

從上文可知Change Buffer是一棵B+樹。當需要實現插入記錄的輔助索引頁不在緩衝池中,輔助索引記錄首先會插入到這棵B+樹中。那麼Insert Buffer中的記錄何時合併(merge)到真正的輔助索引中呢?

merge操作可能發生在以下幾種情況下

  • 輔助索引頁被讀到緩存中
  • Change buffer bitmap頁追蹤到的輔助頁已無可用空間
  • master thread

第一種情況爲當輔助索引頁被讀取到緩衝池中時,例如這在執行正常的SELECT查詢操作,這時需要檢查Insert Buffer Bitmap頁,然後確認該輔助索引頁是否有記錄存放於Insert Buffer B+樹中。若有,則將Insert Buffer B+樹中該頁的記錄插入到該輔助索引頁中。對該頁多次的記錄操作通過幾次操作合併到了原有的輔助索引頁中,因此性能會有大幅提高。

第二種情況Insert Buffer Bitmap 頁用來追蹤每個輔助索引頁的可用空間,並至少有1/32頁的空間。若插入輔助索引記錄時檢測到插入記錄後可用空間會小於1/32頁,則會強制進行一個合併操作,即強制讀取輔助索引頁,將Insert Buffer B+樹中該頁的記錄及待插入的記錄插入到輔助索引頁中。這就是上述所說的第二種情況。

第三種情況就是在Master Thread線程中每秒或每10秒會進行一次Merge Change Buffer的操作,不同之處在於根據線程的工作狀態每次進行merge操作的頁的數量不同。

5. change buffer的使用場景

change buffer主要作用是將記錄的變更緩存下來,merge的時候是真正進行數據更新的時刻,所以在一個數據頁做merge之前,change buffer記錄的變更越多(也就是這個頁面上要更新的次數越多),收益就越大。

因此,對於寫多讀少的業務來說,頁面在寫完以後馬上被訪問到的概率比較小,此時change buffer的使用效果最好。這種業務模型常見的就是賬單類、日誌類的系統。

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