【mysql数据库】bufferPool等相关缓冲池技术
一、bufferPool缓冲池的重要性
- InnoDB存储引擎是基于磁盘存储的。由于CPU速度和磁盘速度之间的鸿沟,InnoDB引擎使用缓冲池技术来提高数据库的整体性能。
- mysql以页为单位与磁盘进行I/O交互,并将页存放在缓冲池中。读写完后不及时释放页的内存空间。如果再有请求访问该页数据,则省去磁盘I/O.
- 通过服务器的配置innodb_buffer_pool_size=268435456 来设置BufferPool的大小,单位是字节 (5.7版本,可以直接动态调整大小,但会阻塞请求,勿要在业务高峰期执行)
- 对于数据库中页的修改操作,首先修改在缓冲池页中,然后以一定的频率刷新到磁盘。通过一种称为checkpoint的机制刷新回磁盘,这也是为了提高数据库的整体性能。
1.1、bufferPool缓冲池的结构
Free链表:用于控制缓冲池中的空闲页,如果需要从硬盘中加载页到缓冲池就从free链表中找到一个空闲页
Flush链表:如果控制块对应的缓冲页,被修改了,则缓冲页就变成脏页,需要加入到flush链表中
LRU链表:从硬盘中把一个页加载到内存中,需要加入到LRU链表,用于管理缓冲页的淘汰机制。
- yong区是热数据,在yong区的1/4后,再次访问需要调整到LRU的头部,old区是冷数据,用于线性预读和随机预读数据放置位置
- innodb_old_blocks_pct默认值为37,表示新读取的页插入到LRU列表尾端37%的位置。
- InnoDB还有一个参数innoDB_old_blocks_time,表示页读取到midpoint位置后需要等待多久才会被加入到LRU列表的热端。
- 【缓存预热】innodb_buffer_pool_dump_at_shutdown=ON表示在关闭MySQL时会把内存中的热数据保存在磁盘里ib_buffer_pool文件中,其保存比率由参数innodb_buffer_pool_dump_pct控制,默认为25%。参数innodb_buffer_pool_load_at_startup=ON表示在启动时会自动加载热数据到Buffer_Pool缓冲池里。
Chunk:是将bufferPool划分为若干个块,用于在数据库运行过程中,调整bufferPool缓冲池的大小
多个bufferPool实例:是为了解决数据库并发访问,提升性能(多段锁的机制)
二、bufferPool缓冲池的change buffer
change buffer的主要目的是将对二级索引的数据操作缓存下来,以减少二级索引的随机I/O,并达到操作合并的效果。
工作原理是有一个或多个非聚集索引,且该索引不是表的唯一索引时,插入时数据会按主键顺序存放,但叶子节点需要离散地访问非聚集索引页,插入性能会降低;此时,插入缓冲生效,先判断非聚集索引页是否在缓冲池中,若在则直接插入;若不在,则先放入一个插入缓冲区,再以一定的频率执行插入缓冲和非聚集索引页子节点的合并操作。
二级索引通常是非唯一的,插入也是很随机的顺序,更新删除也都不是在邻近的位置,所以change buffer就避免了很多随机I/O的产生,将多次操作尽量变为少量的I/O操作。change buffer也是可以持久化的,将change buffer中的操作应用到原数据页、得到最新结果的过程称为merge。
change buffer会占用InnoDB Buffer Pool的部分空间,在磁盘上change buffer会占用共享表空间
- innodb_change_buffering表示缓存所对应的操作,all值表示缓存insert、delete、purges操作
- innodb_change_buffer_max_size参数用于配置change buffer在Buffer Pool中所占的最大百分比,默认是25%,最大可以设置为50%。
三、bufferPool缓冲池的自适应哈希索引
概念:哈希(hash)是一种非常快的查找方法,一般情况下查找的时间复杂度为O(1),即一般仅需要一次查找就能准确定位,B+Tree的查找次数则取决于B+Tree的高度,在大多数的生产环境中,B+Tree的高度一般为3到5层,故需要3~5次的查询。InnoDB存储引擎会监控对表上二级索引的查找。如果发现某二级索引被频繁访问,二级索引就成为热数据;如果观察到建立哈希索引可以带来速度的提升,则建立哈希索引,所以称之为自适应(adaptive)的,即自适应哈希索引(Adaptive HashIndex,AHI)。
自适应哈希索引通过缓冲池的B+Tree构造而来,因此建立的速度很快,而且不需要将整个表都建立哈希索引,InnoDB存储引擎会自动根据访问的频率和模式来为【某些页】建立哈希索引。
- 只适合搜索等值的查询
- innodb_adaptive_hash_index=off/on 控制自适应哈希索引的开启和关闭(维护哈希索引结构是存在额外开销,要慎重衡量选择)
四、bufferPool缓冲池的redo log buffer
redo log buffer是一块内存区域,存放将要写入redo log文件的数据。redo logbuffer大小是通过设置innodb_log_buffer_size参数来实现的。redo log buffer会周期性地刷新到磁盘的redo log file中。
【innodb_flush_log_at_trx_commit】选项控制redo log buffer的内容何时写入redo log file,即控制redo log flush的频率。
- 设置为0:在提交事务时,InnoDB不会立即触发将缓存日志log buffer写到磁盘文件的操作,而是每秒触发一次缓存日志回写磁盘操作,并调用操作系统fsync刷新I/O缓存。
- 设置为1:每次事务提交时MySQL都会立即把log buffer的数据写入redo log file,并且调用操作系统fsync刷新I/O缓存(刷盘操作)。值为1时,每次事务提交都持久化一次,当然是最安全的,但是数据库性能会受影响,I/O负担重,适合对安全要求极高的交易系统场景(建议配置SSD硬盘提高I/O能力)。
- 设置为2:每次事务提交时MySQL都会把redo log buffer的数据写入redo logfile,但是flush(刷到磁盘)操作并不会同时进行,而是每秒执行一次flush(磁盘I/O缓存刷新)。注意,由于进程调度策略问题,并不能保证百分之百的“每秒”。
刷写其实是两个操作,即刷(flush)和写(write)。区分这两个概念(两个系统调用)是很重要的。在大多数的操作系统中,把InnoDB的log buffer(内存)写入日志(调用系统调用write),只是简单地把数据移到操作系统缓存(内存)中,并没有实际持久化数据。
五、数据库Query Cache
- query_cache_size:设置Query Cache所使用的内存大小,默认值为0。大小必须是1024的整数倍,如果不是整数倍,MySQL会自动调整降低最小量以达到1024的倍数。
- query_cache_type:控制Query Cache功能的开关,可以设置为0(OFF)、1(ON)和2(DEMAND)3种。其中,0表示关闭Query Cache功能,任何情况下都不会使用Query Cache;1表示开启Query Cache功能,但是当SELECT语句中使用的SQL_NO_CACHE提示后将不使用Query Cache;2表示开启QueryCache功能,但是只有当SELECT语句中使用了SQL_CACHE提示后才使用QueryCache。
MySQL的Query Cache在大部分情况下只是鸡肋而已,建议全面禁用。