阅读innodb自适应hash index以及mysql aio文档

This commit is contained in:
2025-01-28 18:39:00 +08:00
parent 60609e2442
commit 31be54e703

View File

@@ -1,3 +1,87 @@
- [innodb体系结构](#innodb体系结构)
- [innodb体系结构](#innodb体系结构-1)
- [mysql存储结构](#mysql存储结构)
- [内存结构](#内存结构)
- [Buffer Pool](#buffer-pool)
- [change Buffer](#change-buffer)
- [Adaptive hash index](#adaptive-hash-index)
- [log Buffer](#log-buffer)
- [磁盘存储结构](#磁盘存储结构)
- [system tablespace](#system-tablespace)
- [后台线程](#后台线程)
- [Master Thread](#master-thread)
- [IO Thread](#io-thread)
- [Purge Thread](#purge-thread)
- [Page Cleaner Thread](#page-cleaner-thread)
- [内存](#内存)
- [缓冲池](#缓冲池)
- [缓冲池参数配置](#缓冲池参数配置)
- [innodb\_buffer\_pool\_size](#innodb_buffer_pool_size)
- [LRU List, Free List, Flush List](#lru-list-free-list-flush-list)
- [midpoint](#midpoint)
- [page made young](#page-made-young)
- [youngs/s \& non-youngs/s](#youngss--non-youngss)
- [buffer pool hit rate](#buffer-pool-hit-rate)
- [FreeList](#freelist)
- [Flush List](#flush-list)
- [redo log buffer](#redo-log-buffer)
- [checkpoint](#checkpoint)
- [缩短数据库恢复时间](#缩短数据库恢复时间)
- [缓冲池不够用](#缓冲池不够用)
- [redo log不可用](#redo-log不可用)
- [LSN](#lsn)
- [Fuzzy Checkpoint](#fuzzy-checkpoint)
- [checkpoint种类](#checkpoint种类)
- [Master Thread Checkpoint](#master-thread-checkpoint)
- [FLUSH\_LRU\_LIST\_CHECKPOINT](#flush_lru_list_checkpoint)
- [Async/Sync Flush Checkpoint](#asyncsync-flush-checkpoint)
- [Dirty Page too Much](#dirty-page-too-much)
- [Buffer pool刷新](#buffer-pool刷新)
- [innodb\_max\_dirty\_pages\_pct\_lwm](#innodb_max_dirty_pages_pct_lwm)
- [innodb\_lru\_scan\_depth](#innodb_lru_scan_depth)
- [自适应刷新](#自适应刷新)
- [innodb\_adaptive\_flushing\_lwm](#innodb_adaptive_flushing_lwm)
- [innodb\_adaptive\_flushing](#innodb_adaptive_flushing)
- [Log Buffer](#log-buffer-1)
- [innodb\_flush\_log\_at\_trx\_commit](#innodb_flush_log_at_trx_commit)
- [innodb\_flush\_log\_at\_timeout](#innodb_flush_log_at_timeout)
- [Master Thread](#master-thread-1)
- [每秒钟执行一次的操作](#每秒钟执行一次的操作)
- [每10秒执行的操作](#每10秒执行的操作)
- [change buffer](#change-buffer-1)
- [聚簇索引和辅助索引插入顺序](#聚簇索引和辅助索引插入顺序)
- [change buffer配置](#change-buffer配置)
- [优势](#优势)
- [弊端](#弊端)
- [`innodb_change_buffering`](#innodb_change_buffering)
- [`innodb_change_buffer_max_size`](#innodb_change_buffer_max_size)
- [double write](#double-write)
- [double write结构](#double-write结构)
- [innodb\_doublewrite](#innodb_doublewrite)
- [DETECT\_AND\_RECOVERY](#detect_and_recovery)
- [DETECT\_ONLY](#detect_only)
- [innodb\_doublewrite\_dir](#innodb_doublewrite_dir)
- [innodb\_doublewrite\_pages](#innodb_doublewrite_pages)
- [innodb\_doublewrite\_files](#innodb_doublewrite_files)
- [flush list dobulewrite file](#flush-list-dobulewrite-file)
- [lru doublewrite file](#lru-doublewrite-file)
- [adaptive hash index自适应哈希](#adaptive-hash-index自适应哈希)
- [自适应哈希](#自适应哈希)
- [自适应哈希构建](#自适应哈希构建)
- [访问模式](#访问模式)
- [AHI构建要求](#ahi构建要求)
- [non-hash searches](#non-hash-searches)
- [innodb\_adaptive\_hash\_index](#innodb_adaptive_hash_index)
- [异步io](#异步io)
- [Sync IO](#sync-io)
- [AIO](#aio)
- [io merge](#io-merge)
- [刷新邻接页](#刷新邻接页)
- [启动、关闭和恢复](#启动关闭和恢复)
- [innodb\_fast\_shutdown](#innodb_fast_shutdown)
- [innodb\_force\_recovery](#innodb_force_recovery)
# innodb体系结构 # innodb体系结构
## innodb体系结构 ## innodb体系结构
innodb体系结构由如下部分构成 innodb体系结构由如下部分构成
@@ -498,6 +582,108 @@ doublewirte file命名格式如下所示
#ib_page_size_file_number.dblwr #ib_page_size_file_number.dblwr
``` ```
## adaptive hash index自适应哈希
自适应哈希允许innodb在不牺牲传统食物特性以及可靠性的基础上在工作负载适当buffer pool内存充足的场景下表现的更像in-memory database。
### 自适应哈希
哈希的查找性能较B+树来说较高B+树的查找次数取决于B+树的高度生产环境中B+树的高度通常为3~4层故而需要3~4次查询而哈希通常只需要一次查找就能定位到数据。
#### 自适应哈希构建
innodb监控索引查询并且当观测到建立哈希索引能够加速查询时会自动创建哈希索引故而成为自适应哈希索引AHI
AHI是通过buffer pool中的`B+树页`来构建的,故而构建数度很快。`AHI并不需要根据整张表构建哈希索引`innodb会根据访问频率和模式来自动为某些热点页建立哈希索引。
#### 访问模式
AHI在监控索引访问时要求页的连续访问模式必须是一样的。例如对于`(a,b)`这样的联合索引页,其访问模式存在如下可能场景:
- where a = xxx
- where a = xxx and b = xxx
上面两种场景都会走`(a,b)`联合索引但是在AHI看来其访问模式并不相同。
#### AHI构建要求
在满足对索引页的连续访问模式一样后AHI的构建还有如下要求
- 以相同模式访问了100次
- 待构建的索引页通过该模式访问了N次`N = 页中的记录数 / 16`
即对于制定索引既要求访问该索引的条件相同也要求索引页被多次访问索引页被访问次数达到页中记录数的1/16
在启用AHI后读取和写入速度可以提升2~3倍辅助索引连接性能可以提升5倍。
#### non-hash searches
hash索引只能被用于等值查询对于其他类型查找例如范围查找并不适用。
### innodb_adaptive_hash_index
是否启用自适应哈希索引可以通过`innodb_adaptive_hash_index`变量来控制,当值为`ON`时,代表自适应哈希索引被启用。
hash index是通过index key的前缀来进行构建的prefix可以是任何长度并且只有b树中的一些值能够出现在hash index中。`hash index是为经常被访问的索引页面按需进行构建的`
如果一张表几乎全部都加载到了内存中那么通过hash index能够加速对该表的查询。此时hash index对应的value类似于指针能够直接访问表中的任何元素。
> innodb中存在监控索引搜索的机制如果innodb发现可以通过构建hash index来受益那么其会字段能够构建hash索引。
在某些工作负载下hash index带来的查找加速远远超过了`监控索引搜索`以及`维护hash index结构`带来的开销。
但是在某些高工作负载的场景下hash index可能并不会带来收益此时可以关闭hash index从而减少额外开销。
adaptive hash index是被分区的每个hash index被绑定到一个分区并且每个分区被一个独立的latch保护。
分区数量可以通过`innodb_adaptive_hash_index_parts`来控制默认为8最大可以设置为512.
可以通过`show engine innodb status`中输出的` SEMAPHORES`部分来监控adaptive hash index。如果存在许多线程正在等待`btr0sea.c`中创建的rw latches可以考虑增加adaptive hash index partitions或者禁用adaptive hash index。
## 异步io
为了提升数据库性能innodb采用异步io操作方式。
### Sync IO
传统的Sync IO要求每进行一次io操作都要求当前io操作执行完成后才能执行下一次io操作。
对于同步阻塞io当用户发送了一条索引扫描的查询指令时那么该sql可能需要扫描多个索引页面每次索引页面的扫描需要一次IO操作。sync io需要每次索引扫描完成后再执行下一次索引扫描。
### AIO
对于异步io用户可以在发送一个io指令后立刻再发送另一个io指令并在所有io指令发送后等待所有io操作完成。发送另一个io指令时并不需要等待前面io操作的完成这样可以降低在io阻塞上等待的时间。
#### io merge
aio除了可以无阻塞的执行多条io操作外还可以进行io merge操作即将多个io合并为一个io。通过将多个io请求合并为一个io请求可以提升iops每秒钟执行的io数量
例如,用户需要访问的页(space, page)为`(8,6), (8,7), (8,8)`每个页的大小为16kb那么当使用同步io时需要执行3次io操作。
当时当使用aio时aio会判断`(8,6), (8, 7), (8,8)`这是那个页是连续的那么aio底层只会发送一个io请求从(8,6)开始读取48KB大小的数据。
通过linux命令`iostat`,能够观察`rrqm/s``wrqm/s`(read/write requests merged per second)。
## 刷新邻接页
innodb中提供了刷新邻接页的特性。当刷新脏页时innodb会检测页所在区(extent)中的所有页,如果也是脏页,则会一起执行刷新操作。
通过刷新邻接页的操作可能将不怎么脏的脏页也进行了刷新而该页和快又被变脏而且在使用固态硬盘时固态硬盘拥有较高的iops可能并不太需要该特性。
可以通过`innodb_flush_neighbors`变量来控制是否刷新邻接页。
## 启动、关闭和恢复
### innodb_fast_shutdown
在innodb进行关闭时`innodb_fast_shutdown`参数影响innodb引擎的行为该参数可选值为`0,1,2`默认值为1。
参数各值代表的行为如下:
- 0: mysql数据库关闭时innodb需要完成所有full purge和merge insert buffer并且要将所有的脏页刷新到磁盘中。这需要很长时间来完成`如果在对innodb进行升级时需要将这个参数调整为0并关闭数据库`
- 1 默认值代表不需要完成full purge和merge insert buffer操作但是要将脏页刷新会磁盘
- 2: 代表不完成full purge和merge insert操作也不将脏页刷新回磁盘而是将日志都写到日志文件中这样不会有任何事物的丢失但是下次mysql启动时需要执行恢复操作recovery
### innodb_force_recovery
参数innodb_force_recovery控制innodb引擎的恢复情况。该参数默认为0代表需要恢复时进行所有恢复操作并且当不能有效恢复时例如数据页发生冲突会令mysql宕机并且将错误写入到错误日志中。
innodb_force_recovery的取值如下
- 0默认
- 1(SRV_FORCE_IGNORE_CORRUPT):忽略检查到的冲突页
- 2(SRV_FORCE_NO_BACKGROUND):阻止master thread线程的运行如master thead需要进行full purge这会导致crash
- 3(SRV_FORCE_NO_TRX_UNDO):不进行事务的回滚
- 4(SRV_FORCE_NO_IBUF_MERGE):不进行插入缓冲的合并操作
- 5(SRV_FORCE_NO_UNDO_LOG_SCAN):不查看undo loginnodb会将未提交事务看作已提交
- 6(SRV_FORCE_NO_LOG_REDO):innodb不执行前滚操作
> 如果在数据库发生宕机时存在未提交事务那么将下次数据库启动时会先根据未提交事务的undo log来对数据进行回滚。