MySQL 案例:innodb_buffer_pool_read_requests 解读

2020-12-15 15:51:09 浏览数 (1)

背景

近期时不时会遇到用户结合 MySQL 指标异常的情况来反馈数据库的问题,可能也有很多公司开始重视 DBA 这个职位了吧(这是好事)。也借机研究一下这些指标的细节,本次解读的指标是innodb_buffer_pool_read_requests

问题描述

接到用户的咨询,反馈innodb_buffer_pool_read_requests和 CPU 指标同时出现了突增,希望帮忙定位一下问题的原因,并给出一些建议。

原因分析

既然带上了具体的指标,那么分析起来就会方便很多,由于 requests 和 reads 的指标一般是一起用的,所以翻文档的时候一起看一下官方文档的介绍:

Innodb_buffer_pool_read_requests The number of logical read requests. Innodb_buffer_pool_reads The number of logical reads that InnoDB could not satisfy from the buffer pool, and had to read directly from disk.

官方文档的介绍还是比较简单直白的,检查完用户的监控数据之后,发现 requests 比较高,reads 很少,说明用户的查询并没有涉及到磁盘 IO,但是存在大量逻辑读,因此一般情况下是查询的效率不太高,可能是中小表全表扫描,或者是索引的效率不高,导致查询的时候仍旧扫描了较多的数据。

这里一般的建议是开启 SQL 审计或者调低慢查询的时间阈值,然后再去找对应的语句。

指标解读

虽说问题可以解释清楚,但是文档里面的细节很少,尤其是 requests 的指标只是提了一下逻辑读请求的数量,那么这个 requests 的维度是 SQL 级别的,每个 SQL 一个 request,还是每行数据一个 request?

开源的好处就是遇到不懂的地方可以爬源代码了(MySQL 5.7.31),requests 的指标是 global status 中的,那么 MySQL 一般有这个指标的具体示意以及内部结构体的参数定义,搜一下这个指标后,找到出处:

代码语言:txt复制
./storage/innobase/srv/srv0mon.cc
代码:
......
        /* innodb_buffer_pool_read_requests, the number of logical
        read requests */
        case MONITOR_OVLD_BUF_POOL_READ_REQUESTS:
                buf_get_total_stat(&stat);
                value = stat.n_page_gets;
                break;
......

可以看到源代码里面对这个参数的解释也是非常简略,不过能看到这个参数的值是 n_page_get 决定的,直观的看起来,比较像是 page 的获取数,那么看一下这个参数除了一些获取统计信息的方法以外,还在哪些地方用到了:

代码语言:txt复制
buf_page_get_zip:访问已压缩的 page,比如压缩过的 blob 数据
buf_page_get_gen:通用的 page 访问函数
buf_page_optimistic_get:特殊的访问方式,非通用型
buf_page_get_known_nowait:获取一个已存在的 page,比如说从 AHI 的记录中直接找到具体的 page
buf_page_try_get_func:尝试通过 tablespace id 和 page number 获取 page,如果没找到,则返回 NULL,而不是从磁盘读取

首先可以看出来这个指标就是指代的 page 数量,稍微看了一下通用的 page 获取方法,可以看到一个调用链:

row_search_mvcc -> sel_set_rtr_rec_lock -> buf_page_get_gen,在获取 row record 的时候,会调用这个函数,那么说明:如果多个行用到了同一个 page,那么这个 requests 的指标也会计算多次

PS:可能会有一些优化策略来减少单个 pages 反复读取的问题,不过不在本文探索的范围之内。

那么最初提出的疑问,至此就可以有个明确地回答了:这个 requests 的维度是 SQL 级别的,每个 SQL 一个 request,还是每行数据一个 request?

答曰:维度是数据库的 page,如果多行数据在同一个 page 里面,那么多次访问同一个 page 的时候也会记录多次

总结一下

innodb_buffer_pool_read_requests 这个指标由于记录的是 page 数,在直观的数值上其实是不太好单独用来判断读压力的,毕竟一行数据可能有多个 page,少量的行数可能就会导致这个指标飙升;而重复访问同样的少量 page 也会让这个指标飙升,但是这些 page 可能全部缓存在内存中,实际上不一定会影响查询效率。最好是能结合其他的指标一起来做判断。

0 人点赞