在 MySQL 中使用缓冲池的低可用内​​存和许多 NULL 索引

Low Freeable memory and many NULL index using buffer pool in MySQL

我目前有一个 (AWS) DB.M1.LARGE 实例(7.5GB,2vCPU,40GiB SSD,MySQL 5.6.34)只有 4GB space 在使用中,少于100 个数据库。

出于某种原因,我遇到了高 InnoDB buffer usage,接近 98% 和低 Freeable Memory,不到 600MB。

innodb_buffer_pool_size的当前值为5.7GB

经过一些互联网研究,我发现这个查询列出了所有按大小分组和排序的索引。

select table_name as Table_Name, index_name as Index_Name,
count(*) as Page_Count, sum(data_size)/1024/1024 as Size_in_MB
from information_schema.innodb_buffer_page
group by table_name, index_name
order by Size_in_MB desc;

这是我的查询结果,我不完全理解为什么有那么多 space 用于 NULL 表和 NULL 索引,如果这是一个问题以及为什么Freeable Memory这么低

Index list

这是最近 2 周来自 RDS 控制台的图表

RDS monitoring charts

在新 innodb_buffer_page 查询后更新

根据 Bill 的建议,我 运行 这个新查询,结果如下:

select page_type, page_state, table_name, index_name, 
count(*) as Page_Count, sum(data_size)/1024/1024 as Size_in_MB 
from information_schema.innodb_buffer_page 
group by page_type, page_state, table_name, index_name 
order by Size_in_MB desc;

查询顶部:

First part of the query result

在这两次捕获之间,所有 page_type 都是 INDEX,所有 page_state 都是 FILE_PAGE

Second part of the query result

https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-page-table.html 说:

TABLE_NAME

The name of the table the page belongs to. This column is applicable only to pages with a PAGE_TYPE value of INDEX.

INDEX_NAME 列也是如此。

尝试此查询以获取更多信息:

select page_type, page_state, table_name, index_name, 
  count(*) as Page_Count, sum(data_size)/1024/1024 as Size_in_MB 
from information_schema.innodb_buffer_page 
group by page_type, page_state, table_name, index_name 
order by Size_in_MB desc;

我在您的屏幕截图中看到,许多类型为 INDEX 的缓冲池页面仍然显示 table 和索引名称为 NULL。

我不确定这是什么意思。我查看了 MySQL 来源,如果在 InnoDB 数据字典中找不到索引,它似乎可以将这些值保留为 NULL。但我不确定那是怎么发生的。

https://github.com/mysql/mysql-server/blob/5.6/storage/innobase/handler/i_s.cc#L5007


@C G-K 的回复:

是的,你是对的,我测试过,我看到了不同。我想差异显示了页面的填充率。

select page_type, page_state, table_name, index_name,
  count(*) as Page_Count,
  count(*) * @@innodb_page_size /1024/1024 AS Total_Page_Size_in_MB,
  sum(data_size)/1024/1024 as Size_in_MB
from information_schema.innodb_buffer_page  
group by page_type, page_state, table_name, index_name
order by Size_in_MB desc

+-------------------+------------+--------------+------------+------------+-----------------------+-------------+
| page_type         | page_state | table_name   | index_name | Page_Count | Total_Page_Size_in_MB | Size_in_MB  |
+-------------------+------------+--------------+------------+------------+-----------------------+-------------+
| INDEX             | FILE_PAGE  | `test`.`foo` | PRIMARY    |       1940 |           30.31250000 | 27.87315369 |

有问题吗?当 MySQL 为 运行 时,它通常分配了整个 buffer_pool。

5.7 buffer_pool
x.x various other tables and caches
y.y code (OS, MySQL, etc)
0.6 "freeable" memory
---
7.5 Total

600MB 由 OS 控制,而不是 MySQL。它很可能是缓存在 RAM 中的磁盘块。如果它们匹配磁盘上的内容(即,不是 "dirty"),那么它们可以立即重复使用。

您在 table 中显示的 3.7GB 可能 是 InnoDB 控制下的空闲块。如果是这样,它们将在您执行 INSERTs 等操作时重复使用

(注意:根据我的经验,这个答案的大部分内容是 'guessing'。)

关于 NULL table_names,MySQL 在此处记录:https://dev.mysql.com/doc/refman/8.0/en/innodb-information-schema-buffer-pool-tables.html

This query provides an approximate count of pages that contain system data by excluding pages where the TABLE_NAME value is either NULL or includes a slash / or period . in the table name, which indicates a user-defined table.

也从 Oracle 编辑:(这很复杂)

When table_name is NULL, it means that those pages are available for allocation. Are either free, or used by system. But always available when claimed. NULL is used for all buffer pool blocks that are not index pages or free.