阅读innodb自适应hash index以及mysql aio文档
This commit is contained in:
@@ -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 log,innodb会将未提交事务看作已提交
|
||||||
|
- 6(SRV_FORCE_NO_LOG_REDO):innodb不执行前滚操作
|
||||||
|
|
||||||
|
> 如果在数据库发生宕机时,存在未提交事务,那么将下次数据库启动时,会先根据未提交事务的undo log来对数据进行回滚。
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user