Mysql數據庫InnoDB架構


本文介紹InnoDB存儲引擎架構的主要組件。
1.緩衝池(Buffer Pool)
緩衝池是數據訪問時InnoDB在主內存中緩存表和索引數據的區域。緩衝池允許頻繁訪問的數據直接在內存中處理,這減速了處理的性能。專用數據庫服務器上,通常將80%的物理內存分配給InnoDB緩衝池。
爲了改善大量讀取操作的效率,緩衝池被分成可以存儲多個數據行的數據頁。爲了提高緩衝管理的效率,緩衝池通過數據頁鏈表實現。通過LRU的變種算法,較少使用的數據將因過期而被刷出緩衝。


2.改變緩衝(Change Buffer)
改變緩衝是一種特殊的數據結構,當修改二級索引時,如果被影響的數據頁不再緩衝池中,改變緩衝用來緩衝對這些數據頁的改變。這些也許來自insert,update,或delete操作(DML)的被緩衝的改變,當相關受影響的數據頁稍後被其他讀操作加載到緩衝池時,這些被緩衝的改變將會被合併。
不像簇索引,二級索引通常並非唯一索引,且二級索引的插入操作相對來說更加隨機。類似的,deletes和updates操作也許影響二級索引樹中並不相鄰的數據頁。當後來這些被影響的二級索引數據頁被其他操作讀進緩衝池時,這些改變將被合併,從而避免了從磁盤將二級索引數據頁讀入緩衝池而引起的大量隨機訪問IO的發生。
當系統空閒時,將週期性的把修改的數據頁清除寫到磁盤,或者系統慢關閉期間也會進行這種數據頁清除操作。這種清除操作能將一系列索引值高效的寫入磁盤塊,這比將單個索引值立即寫入磁盤要高效的多。
當有多個二級索引發生修改且影響很多數據行時,改變緩衝的合併也許會持續數個小時。期間,磁盤I/O升高,這也許會導致受限磁盤的查詢變的非常緩慢。事務提交後,改變緩衝合併也許會繼續進行。實際上,服務器重啓後,改變緩衝合併也許會繼續發生。
內存中,改變緩衝會佔據一部分InnoDB緩衝池。磁盤上,改變緩衝爲系統表空間(system tablespace)的一部分,這樣,數據庫重啓後索引改變依然會被緩衝。
改變緩衝中緩衝的數據類型由innodb_change_buffering配置選項確定。
監視改變緩衝
下列選項用於監視改變緩衝:
1)InnoDB Standard Monitor輸出包括改變緩衝的狀態信息。爲了瀏覽監視數據,發佈show engine innodb status命令。
mysql> SHOW ENGINE INNODB STATUS\G
改變緩衝狀態信息在INSERT BUFFER AND ADAPTIVE HASH INDEX部分,標題如下所示:
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
Hash table size 4425293, used cells 32, node heap has 1 buffer(s)
13577.57 hash searches/s, 202.47 non-hash searches/s
2)INFORMATION_SCHEMA.INNODB_METRICS表提供InnoDB Standard Monitor輸出中的大部分信息,另外還有其他信息。爲了瀏覽改變緩衝指標和每個的描述,發佈下列查詢:
mysql> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%ibuf%'\G
3)INFORMATION_SCHEMA.INNODB_BUFFER_PAGE表提供緩衝池中每個數據頁的元數據,其中包括改變緩衝索引和改變緩衝位圖頁。改變緩衝數據頁通過PAGE_TYPE標示。IBUF_INDEX爲改變緩衝索引頁的頁類型,
IBUF_BITMAP爲改變緩衝位圖頁的頁類型。
警告:
查詢INNODB_BUFFER_PAGE表能產生大量的性能開銷。爲了避免影響性能,在測試實例上重現想研究的問題,並在測試實例運行你的查詢。
例如:可以查詢INNODB_BUFFER_PAGE表來確定IBUF_INDEX和IBUF_BITMAP數據頁佔整個緩衝池數據頁的近似百分比。
mysql> SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
WHERE PAGE_TYPE LIKE 'IBUF%') AS change_buffer_pages,
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS total_pages,
(SELECT ((change_buffer_pages/total_pages)*100))Adaptive Hash Index
2330
AS change_buffer_page_percentage;
+---------------------+-------------+-------------------------------+
| change_buffer_pages | total_pages | change_buffer_page_percentage |
+---------------------+-------------+-------------------------------+
| 25 | 8192 | 0.3052 |
+---------------------+-------------+-------------------------------+
4)performance模式提供高級性能監視改變緩衝互斥鎖相關的等待指示。爲了查看改變緩衝指示,發佈下述查詢:
mysql> SELECT * FROM performance_schema.setup_instruments
WHERE NAME LIKE '%wait/synch/mutex/innodb/ibuf%';
+-------------------------------------------------------+---------+-------+
| NAME | ENABLED | TIMED |
+-------------------------------------------------------+---------+-------+
| wait/synch/mutex/innodb/ibuf_bitmap_mutex | YES | YES |
| wait/synch/mutex/innodb/ibuf_mutex | YES | YES |
| wait/synch/mutex/innodb/ibuf_pessimistic_insert_mutex | YES | YES |
+-------------------------------------------------------+---------+-------+


3.自適應哈希索引(Adaptive Hash Index)
自適應哈希索引(AHI)能讓InnoDB在合適的工作負載和大量內存用於緩衝池的系統上,運行起來更像內存數據庫,而同時並不會犧牲可靠性和任何事務相關的特性。該特點能通過innodb_adaptive_hash index選項進行開啓,或者服務器啓動時通過--skip_innodb_adaptive_hash_index關閉。
基於搜索的觀察模式,mysql會用索引鍵前綴建立一個哈希索引。鍵前綴能是任何長度,它也許僅僅是某些值出現於B-tree哈希索引中。哈希索引按照常被訪問的索引數據頁要求建立。如果幾乎整張表可以放於主內存,哈希索引能通過開啓任何元素直接查找,將索引值轉換成某種指針來檢索查詢性能。InnoDB有一個監視索引搜索的機制。如果InnoDB注意到查詢能得益於建立哈希索引,那麼,將會自動創建它。某些工作負載下,哈希索引查找帶來的加速超過監視索引查找和維護索引結構的額外工作。有時,保障自適應哈希索引的讀寫鎖能成爲高負載下的衝突源,這種高負載像多個併發連接等。帶有like和%操作符的查詢一般不會得益於AHI。
對無需自適應哈希索引的負載,將其關閉以減少不必要的性能開銷。因爲難以提前預測該特性是否適用於特定的系統,因此,應該考慮在理想工作負載下開啓和關閉該特性的情況下進行基準測試。mysql5.6及更高版本的架構改變使得其比之前的版本更加適合關閉自適應索引的負載,雖然,默認情況下該特性是開啓的。
mysql5.7中,對自適應索引查找系統進行了分區。每個索引綁定到特定的分區,每個分區由獨立的閂(latch)來保護。分區通過innodb_adaptive_hash_index_parts配置選項來進行控制。早期版本中,自適應哈希索引通過單個閂保護,這樣,其在高負載下容易成爲一個衝突點。innodb_adaptive_hash_index_parts選項默認被設置爲8,其最大設置值爲512。
哈希索引總是基於表的已存在B-tree索引創建。InnoDB能在B-tree定義鍵的任意長度的前綴上創建哈希索引,這主要取決於InnoDB觀察的特定索引的查找模式。哈希索引能是部分的,就是指包含常被訪問的索引數據頁。
用戶可以通過show engine innodb status命令輸出的semaphores部分監視自適應哈希索引的使用和衝突情況。如果看到很多線程正等着btr0sea.c上創建的rw-latch,那麼,也許應該關閉自適應哈希索引。


4.重做日誌緩衝(Redo Log Buffer)
重做日誌緩衝是持有將被寫入重做日誌數據的內存區域。重做日誌緩衝大小由innodb_log_buffer_size配置選項確定。重做日誌緩衝定期被刷出到磁盤上的日誌文件。一個重做日誌緩衝可以讓大事務提交前不必將重做日誌寫到磁盤上。這樣,如果你有操作很多數據行的update,insert或delete,可以將重做日誌緩衝設置大些以節省磁盤I/O。
innodb_flush_log_at_trx_commit選項控制重做日誌緩衝內容如何寫到日誌文件中。innodb_flush_log_at_timeout選項控制重做日誌刷新的頻率。


5.系統表空間(System Tablespace)
InnoDB系統表空間包含InnoDB數據字典(InnoDB相關對象的元數據)和雙寫緩衝(doublewrite buffer),改變緩衝(change buffer)和取消緩衝(undo logs)。系統表空間也包含用戶創建於系統表空間的表和索引的數據。
由於系統表空間被多個表共享,因此,其被認爲是一個共享表空間。系統表空間有一個或多個數據文件組成。默認地,在mysql數據目錄中創建一個叫做ibdata1的系統數據文件。系統數據文件的大小和數量由innodb_data_file_path_startup選項控制。


6.InnoDB數據字典(Innodb Data Dictionary)
InnoDB數據字典由包含用於保持像表,索引和表列等對象軌跡的元數據的內部系統表組成。元數據物理位於InnoDB系統表空間。由於歷史原因,數據字典元數據某種程度上與存儲於InnoDB表元數據文件(.frm文件)中的信息重疊。


7.雙寫緩衝(Doublewrite Buffer)
雙寫緩衝是位於系統表空間內的存儲區域,數據頁被寫到數據文件中前,InnoDB將來自Innodb緩衝區的數據頁寫入該區域。僅僅在將數據頁刷出和寫入到雙寫緩衝區後,InnoDB纔會將數據頁寫入其相應的數據文件。
如果有操作系統,存儲系統,或mysqld進程在寫出數據頁的過程中崩潰,InnoDB稍後將在崩潰恢復期間從雙寫緩衝區找到該數據頁的一個完好拷貝。
雖然數據頁總是被寫兩次,雙寫緩衝區並不像其他很多I/O操作一樣需要兩倍的I/O開銷。通過單個fsync()操作系統調用,數據作爲大的順序數據塊被寫入雙寫緩衝區。
雙寫緩衝區默認在多數場景被開啓。爲了關閉雙寫緩衝,將innodb_doublewrite設置爲0。
如果系統表空間文件(“ibdata文件”)位於支持原子寫的Fusion-io設備,雙寫緩衝自動被關閉,且Fusion-io原子寫用於所有的數據文件。因爲雙寫緩衝設置爲全局的,雙寫緩衝對位於non-Fusion-io硬件上的數據文件也被關閉。該特點僅被Fusion-io硬件支持且僅被linux上的Fusion-io NVMFS開啓。爲了充分裏用該特點,推薦使用O_DIRECT的innodb_flush_method。


8.取消日誌(Undo Logs)
一條取消日誌爲與單個事務相關的取消日誌記錄的集合。一條取消日誌記錄包含關於如何取消某個簇索引記錄上最近改變的信息。如果另一個事務需要看原始數據(作爲一致性讀操作部分),未被修改的數據從取消日誌記錄中被取回。回滾日誌存在於回滾段中的取消日誌段中。回滾段駐留在系統表空間,臨時表空間,和取消表空間內。
InnoDB支持128個回滾段,其中,32個回滾段保留作爲臨時表事務的非重做回滾段。更改臨時表的每個事務(除去只讀事務)被分配兩個回滾段,一個開啓重做的回滾段和一個非重做回滾段。由於只讀事務僅允許修改臨時表,只讀事務僅被分配非重做回滾段。
這樣,還剩96個回滾段可用,其中每個回滾段支持最大1023個併發數據修改事務,總共約允許96k個併發數據修改事務。96k限制假設事務並不修改臨時表。如果所有的數據修改事務頁修改臨時表,那麼,總共允許約32k個併發數據修改事務。


9.每表文件表空間(File-Per-Table Tablespaces)
一個每表文件表空間是一個創建於自己數據文件而非系統表空間的單表表空間。當innodb_file_per_table選項開啓時,表被創建於每表文件表空間。否則,InnoDB將被創建於系統表空間。每表文件表空間通過默認創建於數據庫目錄中的單個.ibd數據文件表示。每表文件表空間支持動態和壓縮行格式,這種格式支持像變長數據的離頁(off-page)存儲和表壓縮。


10.通用表空間(General Tablespaces)
通用表空間可以通過create tablespace語法創建的共享InnoDB表空間。通用表空間能在mysql數據目錄外創建,能容納多張表,也支持所有行格式的表。
通過create table tb1_name...tablespace[=]tablespace_name或alter table tbl_name tablespace [=] tablespace_name語法可以創建共享InnoDB表空間。


11.取消表空間(Undo Tablespace)
取消表空間有一個或多個包含取消日誌的文件組成。InnoDB使用的取消表空間數有innodb_undo_tablespaces配置選項確定。
注意:
innodb_undo_tablespace將來將被啓用和移除。


12.臨時表空間(Temporary Tablespace)
1)簡介
非壓縮的,用戶創建的臨時表和磁盤上的內部臨時表創建於共享臨時表空間。innodb_temp_data_file_path配置選項確定臨時表空間相對路徑,名字,大小和屬性。如果不確定innodb_temp_data_file_path的值,將默認在innodb_data_home_dir目錄下創建一個自動擴展的,名字爲ibtmp1的,稍大於12MB的數據文件。
注意:
mysq5.6中,非壓縮臨時表創建於臨時文件目錄的單獨每表文件表空間,或如果innodb_file_per_table被關閉,創建於數據目錄的InnoDB系統表空間。MySQL5.7中共享臨時表空間的引入除去了創建和移去每個臨時表相關的性能開銷。專用臨時表空間也意味着將不再需要將臨時表元數據存儲於InnoDB的系統表中。
通過row_format=compressed屬性創建的壓縮臨時表,創建於臨時文件目錄的每表文件表空間中。正常關閉或中斷初始化時,臨時表空間將被移去,而每次服務器啓動時,臨時表空間將被重新創建。當臨時表空間被創建時,其收到一個動態產生的空間ID。當臨時表空間不能創建時將不能成功啓動服務器。如果服務器意外終止,臨時表空間將不被移去。這種情況下,數據庫管理員能手工移去臨時表空間或重啓服務器,
重啓服務器將自動移去和重新創建臨時表空間。
臨時表空間不能駐留在一個裸設備上。information_schema.files提供有關InnoDB臨時表空間的元數據。通過類似下面的查詢可以查看臨時表空間的元數據:
mysql> SELECT * FROM INFORMATION_SCHEMA.FILES WHERE TABLESPACE_NAME='innodb_temporary'\G
INFORMATION_SCHEMA.INNODB_TEMP_TABLE_INFO提供關於用戶創建的、當前活躍於InnoDB實例的臨時表的元數據。
2)管理臨時表空間數據文件大小
默認地,臨時表空間數據文件會自動擴展,且按照磁盤臨時表需求自動增長大小。例如:如果一個操作創建一個20MB大小的臨時表,而臨時表空間數據文件創建時的默認大小爲1MB,此時,臨時表空間數據文件將擴展以適應臨時表的大小。當臨時表被刪除時,釋放的空間能被新的臨時表重用,但數據文件保持擴展後的大小。
在使用巨大臨時表或大量臨時表的環境中,自動擴展的臨時表空間數據文件將會變的非常大。長時間運行的使用臨時表的查詢也會導致巨大的臨時表空間數據文件。
爲了確定臨時表空間數據文件是否正在自動擴展,可以檢查innodb_temp_data_file_path的設置:
mysql> SELECT @@innodb_temp_data_file_path;
+------------------------------+
| @@innodb_temp_data_file_path |
+------------------------------+
| ibtmp1:12M:autoextend |
+------------------------------+
爲了查看臨時表空間數據文件的大小,可以像如下那樣查詢information_schema.files表:

mysql> SELECT FILE_NAME, TABLESPACE_NAME, ENGINE, INITIAL_SIZE, TOTAL_EXTENTS*EXTENT_SIZE
AS TotalSizeBytes, DATA_FREE, MAXIMUM_SIZE FROM INFORMATION_SCHEMA.FILES
WHERE TABLESPACE_NAME = 'innodb_temporary'\G
*************************** 1. row ***************************
FILE_NAME: ./ibtmp1
TABLESPACE_NAME: innodb_temporary
ENGINE: InnoDB
INITIAL_SIZE: 12582912
TotalSizeBytes: 12582912
DATA_FREE: 6291456
MAXIMUM_SIZE: NULL
TotalSizeBytes值給出臨時表空間數據文件的當前大小。
另外,你也可以查看操作系統上臨時表空間數據文件的大小。
默認的,臨時表空間數據文件位於innodb_temp_data_file_path配置選項定義的目錄中。如果該選項未指定值,則一個名字爲ibtmp1的臨時表空間數據文件創建於innodb_data_home_dir中,該選項如果未確定,則默認爲mysql數據目錄。
爲了回收臨時表空間數據文件佔用的磁盤空間,你可以重啓mysql服務器。重啓服務器將移去臨時表空間數據文件,且根據innodb_temp_data_file_path選項定義的屬性重新創建臨時表空間數據文件。
爲了防止臨時表空間數據文件變的非常巨大,你可以通過innodb_temp_data_file_path選項設置已給文件的最大值。例如:
[mysqld]
innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:500M
當數據文件達到最大值時,相關查詢將會報錯並指示該表已滿。
innodb_temp_data_file_path的配置需要重啓服務器。
另外,你也可以配置default_tmp_storage_engine和internal_tmp_disk_storage_engine選項,其分別定義用戶創建的和磁盤內部臨時表所用的存儲引擎。兩個選項默認都設置爲InnoDB。
MyISAM存儲引擎爲每張臨時表創建一個單獨的文件,當移去臨時表時該文件也將被移去。
3)歷史表取消日誌(Temporary Table Undo Logs)
臨時表取消日誌位於臨時表空間,用於臨時表及相關對象。臨時表取消日誌並非重做日誌,因爲崩潰恢復期間並不需要它們。它們僅用於服務器運行期間的回滾。這種特殊類型的取消日誌通過避免重做日誌I/O
來改善性能。保留32個回滾段用於修改臨時表和相關對象事務的臨時表取消日誌。


13.重做日誌(Redo Log)
1)簡介
重做日誌是基於磁盤的數據結構,用於崩潰恢復期間矯正被未完成事務寫入的數據。通常操作期間,重做日誌對來自SQL語句或低級API調用的改變InnoDB表數據的需求進行編碼。服務器意外關閉前未被完成的數據文件修改在服務器初始化期間和允許連接前將被自動重演。
默認地,重做日誌由磁盤上名字爲ib_logfile0和ib_logfile1的一套文件表示。mysql按照循環方式對重做日誌文件進行寫入。重做日誌中的數據按照影響記錄進行編碼。重做日誌的數據傳遞通過持續增長的LSN值來表示。
2)重做日誌刷新的組提交
InnoDB,像其他兼容ACID特性的數據庫引擎一樣,事務被提交前將重做日誌刷新到磁盤。InnoDB用組提交功能來對多個類似的刷新需求進行分組,以避免每個提交刷新一次。通過組提交,InnoDB對大約同時提交的多個用戶的事務只進行重做日誌的單個寫入,這樣極大的改善了吞吐量。
 

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