InnoDB在I/O的优化上有个比较重要的特性为预读,预读请求是一个i/o请求,它会异步地在缓冲池中预先回迁多个页面,预计很快就会需要这些页面,这些请求在一个范围内引入所有页面。InnoDB以64个page为一个extent,那么InnoDB的预读是以page为单位还是以extent?
这样就进入了下面的话题,InnoDB使用两种预读算法来提高I/O性能:线性预读(linear read-ahead)和随机预读(randomread-ahead)
为了区分这两种预读的方式,我们可以把线性预读放到以extent为单位,而随机预读放到以extent中的page为单位。线性预读着眼于将下一个extent提前读取到buffer pool中,而随机预读着眼于将当前extent中的剩余的page提前读取到buffer pool中。
线性预读(linear read-ahead)
它可以根据顺序访问缓冲池中的页面,预测哪些页面可能需要很快。通过使用配置参数innodb_read_ahead_threshold,通过调整触发异步读取请求所需的顺序页访问数,可以控制Innodb执行提前读操作的时间。在添加此参数之前,InnoDB只会计算当在当前范围的最后一页中读取整个下一个区段时是否发出异步预取请求。
线性预读方式有一个很重要的变量控制是否将下一个extent预读到buffer pool中,通过使用配置参数innodb_read_ahead_threshold,可以控制Innodb执行预读操作的时间。如果一个extent中的被顺序读取的page超过或者等于该参数变量时,Innodb将会异步的将下一个extent读取到buffer pool中,innodb_read_ahead_threshold可以设置为0-64的任何值,默认值为56,值越高,访问模式检查越严格。
1 2 3 4 5 6 7 |
mysql> show global variables like '%innodb_read_ahead_threshold%'; +-----------------------------+-------+ | Variable_name | Value | +-----------------------------+-------+ | innodb_read_ahead_threshold | 56 | +-----------------------------+-------+ 1 row in set (0.00 sec) |
例如,如果将值设置为48,则InnoDB只有在顺序访问当前extent中的48个pages时才触发线性预读请求,将下一个extent读到内存中。如果值为8,InnoDB触发异步预读,即使程序段中只有8页被顺序访问。你可以在MySQL配置文件中设置此参数的值,或者使用SET GLOBAL需要该SUPER权限的命令动态更改该参数。
在没有该变量之前,当访问到extent的最后一个page的时候,Innodb会决定是否将下一个extent放入到buffer pool中。
随机预读(randomread-ahead)
随机预读方式则是表示当同一个extent中的一些page在buffer pool中发现时,Innodb会将该extent中的剩余page一并读到buffer pool中,由于随机预读方式给Innodb code带来了一些不必要的复杂性,同时在性能也存在不稳定性,在5.5中已经将这种预读方式废弃。要启用此功能,请将配置变量设置innodb_random_read_ahead为ON。
1 2 3 4 5 6 7 |
mysql> show global variables like '%innodb_random_read_ahead%'; +--------------------------+-------+ | Variable_name | Value | +--------------------------+-------+ | innodb_random_read_ahead | OFF | +--------------------------+-------+ 1 row in set (0.01 sec) |
在监控Innodb的预读时候,我们可以通过SHOW ENGINE INNODB STATUS命令显示统计信息,通过Pages read ahead和evicted without access两个值来观察预读的情况,或者通过两个状态值,以帮助您评估预读算法的有效性。
1 2 3 4 5 6 7 8 9 |
mysql> show global status like '%Innodb_buffer_pool_read_ahead%'; +---------------------------------------+-------+ | Variable_name | Value | +---------------------------------------+-------+ | Innodb_buffer_pool_read_ahead_rnd | 0 | | Innodb_buffer_pool_read_ahead | 0 | | Innodb_buffer_pool_read_ahead_evicted | 0 | +---------------------------------------+-------+ 3 rows in set (0.00 sec) |
而通过SHOW ENGINE INNODB STATUS得到的Pages read ahead和evicted without access则表示每秒读入和读出的pages:Pages read ahead 1.00/s, evicted without access 9.99/s。
当微调innodb_random_read_ahead设置时,此信息可能很有用 。