1.InnoDB缓存机制
InnoDB用一块内存区做IO缓存池,该缓存池不仅用来缓存InnoDB的索引块,而且也用来缓存InnoDB的数据块,这一点与MyISAM不同。
在内部,InnoDB缓存池逻辑上由 free list、flush list和LRU list组成。顾名思义,free list是空闲缓存块列表,flush list是需要刷新到磁盘的缓存块列表,而LRU list是 InnoDB正在使用的缓存块,它是 InnoDB buffer pool的核心。
InnoDB使用的LRU算法与MyISAM的“中点插入策略”LRU算法很类似,大致原理是:将LRU list分为 young sublist和 old sublist,数据从磁盘读入时,会将该缓存块插入到LRU list的“中点”,即 old sublist的头部;经过一定时间的访问(由innodb_old_blocks_time系统参数决定),该数据块将会由 old sublist转移到young sublist的头部,也就是整个LRU list的头部;随着时间的推移,young sublist和 old sublist中较少被访问的缓存块将从各自链表的头部逐渐向尾部移动;需要淘汰数据块时,优先从链表尾部淘汰。这种设计同样是为了防止偶尔被访问的索引块将访问频繁的热块淘汰。
2.innodb_buffer_pool_size的设置
innodb_buffer_pool_size 决定 InnoDB 存储引擎表数据和索引数据的最大缓存区大小。在保证操作系统及其他程序有足够内存可用的情况下,innodb_buffer_pool_size的值越大,缓存命中率越高,访问InnoDB表需要的磁盘I/O就越少,性能也就越高。在一个专用的数据库服务器上,可以将 80%的物理内存分配给 InnoDB buffer pool,但一定要注意避免设置过大而导致页交换。
innodb_buffer_pool_size=2G
通过以下命令查看 buffer pool的使用情况:
mysqladmin -S /tmp/mysql.sock ext|grep -i innodb_buffer_pool
可用以下公式计算InnoDB缓存池的命中率:
(1-innodb_buffer_pool_read/innodb_buffer_pool_read_request)*100
如果命中率太低,则应考虑扩充内存、增加innodb_buffer_pool_size的值。
3.调整old sublist大小
在LRU list中,old sublist的比例由系统参数 innodb_old_blocks_pct决定,其取值范围是5~95,默认值是37(约等于3/8)。通过以下命令可以查看其当前设置:
mysql> show global variables like ‘%innodb_old_blocks_pct%’;
可以根据 InnoDB Monitor的输出信息来调整 innodb_old_blocks_pct的值。例如,在没有较大表扫描或索引扫描的情况下,如果 young/s 的值很低,可能就需要适当增大innodb_old_blocks_pct的值或减小innodb_old_blocks_time的值。
4.调整innodb_old_blocks_time的设置
可以根据 InnoDB Monitor的输出信息来调整 innodb_old_blocks_time的值。在进行表扫描时,如果non-youngs/s很低,young/s很高,就应考虑将innodb_old_blocks_time适当调大,以防止表扫描将真正的热数据淘汰。更酷的是,这个值可以动态设置,如果要进行大的表扫描操作,可以很方便地临时做调整。
5.调整缓存池数量,减少内部对缓存池数据结构的争用
InnoDB的缓存系统引入了innodb_buffer_pool_instances配置参数,对于较大的缓存池,适当增大此参数的值,可以降低并发导致的内部缓存访问冲突,改善性能。
6.控制 innodb buffer刷新,延长数据缓存时间,减缓磁盘 I/O
在InnoDB找不到干净的可用缓存页或检查点被触发等情况下,InnoDB的后台线程就会开始把“脏的缓存页”回写到磁盘文件中,这个过程叫缓存刷新。
InnoDB buffer pool的刷新快慢主要取决于两个参数。一个是innodb_max_dirty_pages_pct,它控制缓存池中脏页的最大比例,默认值是75%,如果脏页的数量达到或超过该值,InnoDB的后台线程将开始缓存刷新。另一个是innodb_io_capacity,它代表磁盘系统的IO能力,其值在一定程度上代表磁盘每秒可完成 I/O 的次数。innodb_io_capacity 的默认值是 200,对于转速较低的磁盘,如7200RPM的磁盘,可将innodb_io_capacity的值降低到100,而对于固态硬盘和由多个磁盘组成的盘阵,innodb_io_capacity的值可以适当增大。
可以根据一些InnoDB Monitor的值来调整innodb_max_dirty_pages_pct和innodb_io_capacity。例如,若innodb_buffer_pool_wait_free的值增长较快,则说明InnoDB经常在等待空闲缓存页,如果无法增大缓存池,那么应将innodb_max_dirty_pages_pct的值调小,或将innodb_io_capacity的值提高,以加快脏页的刷新。
7.InnoDB doublewrite
默认情况下,InnoDB doublewrite是开启的,可以用以下命令查看:
mysql> show global variables like ‘%doublewrite%’;