innodbbufferpool相關特性
背景
innodb buffer pool作為innodb最重要的快取,其快取命中率的高低會直接影響資料庫的效能。因此在資料庫發生變更,比如重啟、主備切換例項遷移等等,innodb buffer poll 需要一段時間預熱,期間資料庫的效能會受到明顯影響。
另外mysql 5.7以前innodb buffer pool快取大小修改不是動態的,重啟才能生效。因此innodb buffer pool的預熱和innodb buffer pool大小的動態修改,對效能要求較高的應用來說是不錯的特性,下面我來看看這兩個特性的具體實現。
buffer pool 預熱
mysql 5.6以後支援buffer pool預熱功能。引入了以下引數, 引數具體含義參見官方文件
innodb_buffer_pool_load_now
innodb_buffer_pool_dump_now
innodb_buffer_pool_load_at_startup
innodb_buffer_pool_dump_at_startup
innodb_buffer_pool_filename
buffer pool預熱分為dump過程和load過程,均由後臺執行緒buf_dump_thread完成。
比如使用者發起set命令
set global innodb_buffer_pool_dump_now=on;
set global innodb_buffer_pool_load_now=on;
set 命令會立刻返回,具體操作由buf_dump_thread來實現。
- dump 過程
鎖buf_pool
遍歷LRU連結串列,將(space, pageno) 先收集到陣列
釋放鎖
再將資料寫入innodb_buffer_pool_filename定有的檔案中
- load過程
從檔案讀入陣列
按(space,pageno)排序資料
依次同步讀取頁到buffer pool中
dump過程一般比較快,而load過程相對要慢些。
通過Innodb_buffer_pool_dump_status
、Innodb_buffer_pool_load_status
可檢視dump/load的狀態
另外5.7引入了performance_schema.events_stages_current來顯示load進度,每load 32M會更新一條進度資訊
select * from performance_schema.events_stages_current;
THREAD_ID 19
EVENT_ID 1367
END_EVENT_ID NULL
EVENT_NAME stage/innodb/buffer pool load
SOURCE buf0dump.cc:619
TIMER_START 33393877311000
TIMER_END 33398961258000
TIMER_WAIT 5083947000
WORK_COMPLETED 0
WORK_ESTIMATED 1440
NESTING_EVENT_ID NULL
NESTING_EVENT_TYPE NULL
WORK_ESTIMATED表示總page數
WORK_COMPLETED表示當前已load page數
dump檔案的資料格式如下
#cat ib_buffer_pool |more
0,7
0,1
0,3
0,2
0,4
0,11
0,5
0,6
dump檔案比較簡單,我們可以編輯此檔案來預載入指定page,比較靈活。
buffer pool 動態調整大小
5.7 開始支援buffer pool 動態調整大小,每個buffer_pool_instance
都由同樣個數的chunk組成(chunks陣列), 每個chunk記憶體大小為innodb_buffer_pool_chunk_size
(實際會偏大5%,用於存放chuck中的block資訊)。buffer pool以innodb_buffer_pool_chunk_size
為單位進行動態增大和縮小。調整前後innodb_buffer_pool_size
應一直保持是innodb_buffer_pool_chunk_size
*innodb_buffer_pool_instances
的倍數。
同樣的buffer pool動態調整大小由後臺執行緒buf_resize_thread
,set命令會立即返回。通過InnoDB_buffer_pool_resize_status
可以檢視調整的執行狀態。
-
resize流程
- 如果開啟了AHI,需禁用AHI
-
如果是收縮記憶體
- 計算需收縮的chunk數, 從chunks開始尾部刪除指定個數的chunk.
- 鎖buf_pool
- 從free_list中摘除待刪chunk的page放入待刪連結串列buf_pool->withdraw
- 如果待刪chunk的page為髒頁,則刷髒
- 重新載入LRU中要刪除的頁,從LRU中摘除,重新從free列表獲取page老的page放入待刪連結串列buf_pool->withdraw
- 釋放buffer pool鎖
- 如果需收縮的chunk pages沒有收集全,重複2-6
-
開始resize
- 鎖住所有instance的buffer_pool,page_hash
- 收縮pool:以chunk為單位釋放要收縮的記憶體
- 清空withdraw列表buf_pool->withdraw
- 增大pool:分配新的chunk
- 重新分配buf_pool->chunks
- 如果改變/縮小超過2倍,會重置page hash,改變桶大小
- 釋放buffer_pool,page_hash鎖
- 如果改變/縮小超過2倍,會重啟和buffer pool大小相關的記憶體結構,如鎖系統(lock_sys_resize),AHI(btr_search_sys_resize), 資料欄位(dict_resize)等
- 如果禁用了AHI,此時開啟
由上可以看出,擴大記憶體比縮小記憶體相對容易些。縮小記憶體時,如果遇到有事務一直未提交且佔用了待收縮的page時,導致收縮一直重試,error log會列印這種重試資訊,
包含可能引用此問題的事務資訊。為了避免頻繁重試,每次重試的時間間隔會指數增長。
以上步驟中resize階段buffer pool會不可用,此階段會鎖所有buffer pool, 但此階段都是記憶體操作,時間比較短。收縮記憶體階段耗時可能會很長,也有一定影響,但是每次都是以instance為單位進行鎖定的。
總的來說,buffer pool 動態調整大小對應用的影響並不大。
- 重新載入LRU中要刪除的頁的影響
search 過程中btr遊標儲存的page可能重新載入過,自適應雜湊儲存的root page也可能重新載入過, 都需要重新讀取。
總結
buffer pool 預熱 和buffer pool 動態調整大小,這兩功能相輔相承的。buffer pool 動態調整大小隻適用於例項在主機本地升級的情況,如果使用者修改buffer pool大小,同時涉及跨機遷移,那麼buffer pool 預熱功能就排上用場了。
另外buffer pool 動態調整儘量在業務低鋒時進行。
相關文章
- C++ 11 新特性之容器相關特性C++
- Oracle相關NUMA特性淺析Oracle
- WebView的基本使用及相關特性WebView
- MySQL 5.7 學習心得之安全相關特性MySql
- CSS與中文相關的一些特性CSS
- MySQL 8.0 18個管理相關的新特性MySql
- LINQ系列:C#中與LINQ相關特性C#
- Oracle 18c新特性詳解 - 表和表空間相關的新特性Oracle
- Oracle 21c新特性預覽與日常管理相關的幾個新特性Oracle
- SCM通道模型和SCME通道模型的matlab特性模擬,對比空間相關性,時間相關性,頻率相關性模型Matlab
- 11g新特性 密碼錯誤驗證延遲特性的相關驗證密碼
- MySQL 8.0 20個 InnoDB 及資料字典相關的新特性MySql
- vite + ts 快速搭建 vue3 專案 以及介紹相關特性ViteVue
- RHEL 7特性說明(九):Web伺服器和相關服務Web伺服器
- PHP相關PHP
- MyBatis相關MyBatis
- Docker相關Docker
- swift相關Swift
- Oracle相關Oracle
- Spark相關Spark
- oracle 相關Oracle
- 相關工具
- sql相關SQL
- PDN相關
- 【Unity】相關Unity
- Git相關Git
- Cookie相關Cookie
- bean相關Bean
- 硬碟相關硬碟
- elasticsearch相關Elasticsearch
- nginx相關Nginx
- mysql 相關MySql
- npm 相關NPM
- RocketMQ關鍵特性MQ
- solaris10_相關命令_處理器_相關
- 統計學三大相關係數之Pearson相關係數、Spearman相關係數
- 相關子查詢&非相關子查詢概念
- Oracle相關命令Oracle