InnoDB存儲引擎是MySql第一個完整支持事務的存儲引擎,最早由第三方公司開發,並不是MySql的官方引擎,在MySql 5.6後被作爲默認引擎推出。
特點
InnoDB設計是爲OLTP(在線事務處理類型)應用設計,支持事務是最大的特點,此外還有如下特點:
- 事務:完整的ACID及4級事務隔離級別支持;
- 基於行鎖設計:支持行鎖、表鎖,可通過擴展sql主動S和X鎖,不能主動加表鎖;
- 支持外鍵:可以設定外鍵及外鍵的完整性約束;
- 支持MVVC:多版本併發控制技術,實現了多個版本數據的讀寫;
- 一致性非鎖定讀:類似Oracle,提高併發,不是所有的讀都會加鎖,大部分讀不加鎖;
InnoDB的版本
InnoDB的跨界版本是1.0.x,建議使用最新版本獲取更好的性能;
體系結構
InnoDB能很好的利用內存和CPU,它的大部分操作都是利用異步IO技術,屏蔽磁盤和內存的速度差,從而獲得更高的性能;
- 多個後臺線程:通過多個後臺線程,每個線程完成自己的任務,後臺線程的主要作用是刷新內存池中的數據,保持磁盤和內存數據一致;
- 內存池:使用內存緩衝技術,建立多種緩衝池來緩衝數據、索引,內存管理採用基於頁的管理方式,讓讀寫效率更高;
InnoDB的核心線程
- Master Thread:核心線程,將數據異步刷新到磁盤,分爲多種狀態,每秒、每10秒的處理邏輯都不同;
- IO Thread : 採用AIO異步刷新數據到磁盤;
- Purge Thread:清理線程,實際執行update、insert、delete操作,回收undo頁;
- Page Cleander Thread:刷新髒頁數據到磁盤,保持數據同步;
內存池
InnoDB通過內存池技術來解決磁盤讀寫速度問題,其內存池管理結構如下:
可以看到,InnoDB是通過頁的方式來管理數據,類似操作系統的內存管理方式,熱點頁常駐內存,採用LRU等算法進行頁的管理,InnoDB通過多種參數和配置可以影響內存池大小和數據頁的換入換出。
InnoDB每個page的大小是16k
內存池參數
在mysql中可以通過如下參數影響InnoDB內存池的大小及行爲:
觀察InnoDB狀態:Show engine innodb status \G
內存池大小:innodb_buffer_pool_size;
page被hit多少次後加入LRU列表的熱點區:innodb_old_blocks_time
InnoDB狀態參數的含義:
Buffer Pool Hit Rate : 緩存命中策略 不應該小於 95%
Free Buffers + Buffer Pool Size != DataBase Size
重做日誌
爲了實現數據庫事務,基本上所有的數據庫引擎都需要重做日誌,重做日誌包括:redo log 和undo log,統稱重做日誌,重做日誌保證了事務的原子性、一致性、持久性,但是重做日誌本身會帶來開銷。
Checkpoint技術
檢查點技術被很多需要保證系統高可用的程序採用,InnoDB爲了解決磁盤的速度問題,採用內存緩衝方式,也就是很多最新的數據都是在內存中的,但是內存不是持久的,一旦內存斷電,這些修改和操作沒有更新到物理文件中,那麼就會造成數據的丟失和不一致性。InnoDB使用一些技術來保證不會發生這些情況。
InnoDB採用兩種方式將數據異步刷新到磁盤,保證高可用和數據一致性:
- 通過多線程,尤其是核心Master Thread使用一些策略來將數據、日誌、操作刷新到磁盤;
- 檢測點技術,在一些關鍵的點上觸發磁盤操作,將數據、日誌、操作刷新到磁盤;
InnoDB的檢查點技術主要目的:
- 縮短數據庫恢復時間:減少恢復數據量;
- 緩衝池不夠的時候,將髒頁刷新到磁盤,釋放緩衝或者防止數據不一致;
- 重做日誌不可用時,刷新到磁盤,防止重做日誌丟失;
Checkpoint的核心技術是通過LSN(log sequence number)來標記版本號,很多增量備份工具也是使用這個特性。
Checkpoint的觸發時機:
- 數據庫關閉時,觸發Sharp Checkpoint;
- Master Thread 每十幾秒觸發一次 Fuzzy Checkpoint;
- 頁空間不足的時候時觸發Fuzzy Checkpoint;
- 重做日誌不足,這時磁盤空間不夠了,日誌達到了指定大小,覆蓋日誌失敗了,都觸發Fuzzy Checkpoint;
- 內存池中髒頁太多觸發Fuzzy Checkpoint。
InnoDB的一些關鍵技術
關鍵技術和特性不一樣,關鍵技術是實現過程中的一些做法,這些做法帶來了特性。下面是InnoDB採用的一些關鍵技術,有些是獨創的,極大的提高了InnoDB的性能。
- 插入緩衝:insert buffer,解決輔助索引的插入性能問題;
- 兩次寫:double write,提高數據的可靠性,保證數據一致;
- 自適應哈希索引:adaptive hash index,提升索引效率;
- 異步IO:Async IO,使用異步IO不進行同步等待,可以一次發出多個IO指令,底層還會合並多個IO到一次IO;
- 刷新鄰接表:提升髒頁刷新效率。
Insert Buffer
對於非聚集類索引,也叫輔助索引,如果索引不是唯一的,不需要做唯一性校驗,InnoDB會先將索引放入到緩衝區不會每次都調整索引的B+樹,大致思路:
- 每次insert的時候,如果輔助索引字段不是唯一的,不需要做唯一性校驗;
- InnoDB 先不去實際insert index,不刷新磁盤,也不會產生B+樹的旋轉,也就不會引起隨機的IO,等到一定時機,將多個索引的insert merge爲一個insert,提高索引的插入效率。
merge insert buffer的時機:
- 輔助索引頁被讀取到緩衝池中;
- Insert Buffer Bitmap追蹤到輔助索引頁無可用空間;
- Master Thread觸發;
Double Write
提高數據可靠性,尤其是將髒頁刷新到磁盤的時候,防止如果部分寫入失敗了,那麼將產生數據不一致情況;
自適應Hash索引
InnoDB通過監控B+ Tree的索引,如果適用Hash索引,則建立Hash索引。在實際生產環節中,B+ Tree的高度一般爲3 - 4,需要 3 - 4的邏輯IO,遠沒有Hash索引快。
Hash索引僅適用於等值索引,不適合範圍索引,也就是如果頻繁的用where id > ‘100’ 這類操作不會建立自適應Hash索引。
AIO
異步IO,連續發出多個IO,進行IO Merge,提升磁盤的IOPS。
刷新鄰接表
刷新dirty的page時會檢查這個page所在的區域的所有page,如果這些page也是dirty,則一起刷新,通過AIO的merge操作,提升性能。機械硬盤有很大用途;