《MySQL · 8.0版本更新 · 性能優(yōu)化篇》要點(diǎn):
本文介紹了MySQL · 8.0版本更新 · 性能優(yōu)化篇,希望對(duì)您有用。如果有疑問,可以聯(lián)系我們。
本文主要總結(jié)下MySQL在8.0版本和性能相關(guān)的一些改動(dòng),隨著新的小版本的發(fā)布,本文將不斷進(jìn)行更新,直到正式GA.
已更新版本
MySQL 8.0.0
MySQL 8.0.0
WL#9387: InnoDB: Group purging of rows by table ID
這個(gè)問題最早是facebook的工程師Domas報(bào)的一個(gè)bug,InnoDB使用多線程來進(jìn)行Undo Purge操作,但分配undo的策略不太合理,直接輪詢分配.這意味著如果從一張表上刪除大量數(shù)據(jù),這N個(gè)purge線程可能產(chǎn)生大量的索引鎖沖突(例如索引頁合并及重組織)
在WL#9387中,在parse undo log時(shí),通過table_id進(jìn)行分組存儲(chǔ),在分發(fā)時(shí)確保同一個(gè)table id的記錄被分配給同一個(gè)線程.(參考函數(shù) trx_purge_attach_undo_recs
)
當(dāng)然這也意味著合理的不會(huì)產(chǎn)生沖突的單表操作, 無法利用到多線程purge了,也算是一個(gè)弊端.
WL#8423: InnoDB: Remove the buffer pool mutex
這個(gè)算是眾望所歸的改進(jìn)了,由Percona貢獻(xiàn)的補(bǔ)丁(bug#75534),主要是對(duì)InnoDB的buffer pool mutex這個(gè)大鎖進(jìn)行了拆分,降低鎖沖突:
Name | Desc |
---|---|
buf_pool_t::LRU_list_mutex | 用于保護(hù)LRU鏈表,例如從LRU鏈表上刷臟或驅(qū)逐Page |
buf_pool_t::free_list_mutex | 保護(hù)free list及withdraw list(online resize) |
buf_pool_t::zip_free_mutex | 保護(hù)zip_free數(shù)組,該數(shù)組用于維護(hù)對(duì)壓縮表產(chǎn)生的非標(biāo)準(zhǔn)page size的內(nèi)存維護(hù), ref buf/buf0buddy.cc |
buf_pool_t::zip_hash_mutex | 保護(hù)zip_hash, 其中存儲(chǔ)壓縮頁block |
buf_pool_t::flush_state_mutex | 保護(hù)init_flush, n_flush, no_flush等數(shù)組 |
分配空閑block(buf_LRU_get_free_block
):
從free list獲取: buf_pool_t::free_list_mutex
從unzip_lru/lru上驅(qū)逐一個(gè)空閑page,需要buf_pool_t::LRU_list_mutex
批量掃描LRU(buf_do_LRU_batch
): buf_pool_t::LRU_list_mutex
批量掃描FLUSH_LIST(buf_do_flush_list_batch
): buf_pool_t::flush_list_mutex
臟頁加入到flush_list(buf_flush_insert_into_flush_list
): buf_pool_t::flush_list_mutex
臟頁寫回磁盤后,從flush list上移除(buf_flush_write_complete
): buf_pool_t::flush_state_mutex/flush_list_mutex
從LRU上驅(qū)逐Page(buf_LRU_free_page
):buf_pool_t::LRU_list_mutex, 及buf_pool_t::free_list_mutex(buf_LRU_block_free_non_file_page
)
buf_flush_LRU_list_batch
使用mutex_enter_nowait 來獲取block鎖,如果獲取失敗,說明正被其他session占用,忽略該block.
有些變量的修改從通過buf_pool_t::mutex保護(hù),修改成通過memory barrior來保護(hù)(os_rmb
or os_wmb
), 例如下面幾個(gè)函數(shù)中均有體現(xiàn):
btr_search_enable()buf_resize_thread()buf_get_withdraw_depth()buf_LRU_get_free_block()
通過對(duì)鎖的拆分,降低了全局大鎖的競(jìng)爭(zhēng),提升了buffer pool的擴(kuò)展性,這個(gè)特性其實(shí)在Percona Server中很多年前就有了, 但直到MySQL8.0版本才合并進(jìn)來.
WL#7170: InnoDB buffer estimates for tables and indexes
主要是用于為優(yōu)化器提供更準(zhǔn)確的信息,即數(shù)據(jù)是存在與磁盤還是內(nèi)存中, 這樣優(yōu)化器可以更準(zhǔn)確的做出代價(jià)計(jì)算.
增加一個(gè)全局對(duì)象(buf_stat_per_index_t
)來管理所有的索引頁計(jì)數(shù)
為了避免引入新的全局鎖開銷,實(shí)現(xiàn)并使用一個(gè)lock-free的hash結(jié)構(gòu)("include/ut0lock_free_hash.h
)來存儲(chǔ)索引信息,key值為索引id.(目前索引id具有唯一性,但不排除未來可能發(fā)生改變).
增加計(jì)數(shù):
1. Page剛從磁盤讀入內(nèi)存 (buf_page_io_complete --> buf_page_monitor
)
2. 創(chuàng)建一個(gè)新的page (btr_page_create
)
遞減計(jì)數(shù): Page從LRU上釋放時(shí)進(jìn)行遞減(buf_LRU_block_remove_hashed
)
增加新的information_schema.innodb_cached_indexs 打印每個(gè)索引在內(nèi)存中的page個(gè)數(shù),其結(jié)構(gòu)如下:
mysql> show create table INNODB_CACHED_INDEXES\G*************************** 1. row ***************************
Table: INNODB_CACHED_INDEXES
Create Table: CREATE TEMPORARY TABLE `INNODB_CACHED_INDEXES` (
`SPACE_ID` int(11) unsigned NOT NULL DEFAULT '0',
`INDEX_ID` bigint(21) unsigned NOT NULL DEFAULT '0',
`N_CACHED_PAGES` bigint(21) unsigned NOT NULL DEFAULT '0'
) ENGINE=MEMORY DEFAULT CHARSET=utf8
1 row in set (0.00 sec)### 和表名/索引名關(guān)聯(lián)SELECT
tables.name AS table_name,
indexes.name AS index_name,
cached.n_cached_pages AS n_cached_pages
FROM
information_schema.innodb_cached_indexes AS cached,
information_schema.innodb_sys_indexes AS indexes,
information_schema.innodb_sys_tables AS tables
WHERE
cached.index_id = indexes.index_id
AND
indexes.table_id = tables.table_id;
相關(guān)worklog: WL#7168: API for estimates for how much of table and index data that is in memory buffer
WL#9383: INNODB: ADD AN OPTION TO TURN OFF/ON DEADLOCK CHECKER
增加選項(xiàng),可以動(dòng)態(tài)關(guān)閉死鎖檢測(cè),這對(duì)諸如熱點(diǎn)更新這樣的場(chǎng)景效果顯著,之前已專門寫了篇博客,感興趣的自取
Bug#77094
這個(gè)優(yōu)化來自alisql的貢獻(xiàn),主要是優(yōu)化了InnoDB Redo的擴(kuò)展性問題,通過雙buffer機(jī)制,允許在寫日志到磁盤的同時(shí),也允許進(jìn)行mtr commit,具體參閱我寫的這篇月報(bào)
WL#7093: Optimizer provides InnoDB with a bigger buffer
為了減少對(duì)Btree的鎖占用,InnoDB在讀取數(shù)據(jù)時(shí)實(shí)際上是有一個(gè)小的緩存buffer.對(duì)于連續(xù)記錄掃描,InnoDB在滿足比較嚴(yán)格的條件時(shí)采用row cache的方式連續(xù)讀取8條記錄(并將記錄格式轉(zhuǎn)換成MySQL Format),存儲(chǔ)在線程私有的row_prebuilt_t::fetch_cache
中;這樣一次尋路就可以獲取多條記錄,在server層處理完一條記錄后,可以直接從cache中取數(shù)據(jù)而無需再次尋路,直到cache中數(shù)據(jù)取完,再進(jìn)行下一輪.
在WL#7093中引入了新的接口,由于優(yōu)化器可以估算可能讀取的行數(shù),因此可以提供給存儲(chǔ)引擎一個(gè)更合適大小的row buffer來存儲(chǔ)需要的數(shù)據(jù).大批量的連續(xù)數(shù)據(jù)掃描的性能將受益于更大的record buffer.
Record buffer由優(yōu)化器來自動(dòng)決定是否開啟,增加新的類Record_buffer
進(jìn)行管理, Record buffer的大小最大不超過128KB, 目前是hard code的,不可以配置.
判斷及分配record buffer函數(shù): set_record_buffer
, 并通過新的API接口(handler::ha_set_record_buffer
)傳到引擎層
buffer本身是引擎無關(guān)的,在sever層分配,通過handler成員m_record_buffer傳遞到引擎層.
增加新的接口,判斷是否支持Record buffer, 目前僅InnoDB支持,需要滿足如下條件 (ref set_record_buffer
):
access type 不是 ref, ref_or_null, index_merge, range, index 或者ALL
不是臨時(shí)表
不是loose index scan
進(jìn)入InnoDB引擎層判斷((
row_prebuilt_t::can_prefetch_records)
)
return select_lock_type == LOCK_NONE // 只讀查詢
&& !m_no_prefetch // 允許prefetch
&& !templ_contains_blob // 沒有BLOB, TEXT, JSON, GEOMETRY這些大列
&& !templ_contains_fixed_point // 不是空間數(shù)據(jù)類型DATA_POINT
&& !clust_index_was_generated // 需要用戶定義的primary key 或者唯一索引(被隱式的用作Pk)
&& !used_in_HANDLER // 不是通過HANDLER拜訪的
&& !innodb_api // 不是通過類似innodb memcached拜訪的
&& template_type != ROW_MYSQL_DUMMY_TEMPLATE //不是check table
&& !in_fts_query; // 不是全文索引查詢
在InnoDB中,當(dāng)record buffer被配置時(shí),就使用server層提供的record buffer,而不是row_prebuilt_t::fetch_cache
官方博客對(duì)此改進(jìn)的介紹:http://mysqlserverteam.com/mysql-8-0-faster-batch-record-retrieval/
WL#9250: Split LOCK_thd_list and LOCK_thd_remove mutexes
該Worklog的目的是改進(jìn)短連接場(chǎng)景下的性能,對(duì)thd list的操作可能導(dǎo)致比較高的鎖競(jìng)爭(zhēng).
辦理方案也比較傳統(tǒng),就是進(jìn)行分區(qū),將鏈表thd_list劃分成多個(gè)數(shù)組,目前為8個(gè)分區(qū),相應(yīng)的鎖LOCK_thd_remove
和LOCK_thd_list
鎖也進(jìn)行了分區(qū).
維易PHP培訓(xùn)學(xué)院每天發(fā)布《MySQL · 8.0版本更新 · 性能優(yōu)化篇》等實(shí)戰(zhàn)技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養(yǎng)人才。
轉(zhuǎn)載請(qǐng)注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/8017.html