先看一些背景
如何计算内存利用率
read_buffer_size、 read_rnd_buffer_size 、sort_buffer_size、join_buffer_size和tmp_table_size ,以及其他一些变量。默认情况下,所有这些都工作得很好,因为分配小而高效。因此,主要的潜在问题变成了我们分配的许多连接可以保持这些缓冲区一段时间并增加额外的内存压力。理想的情况是控制打开(和使用)的连接数,并尝试将该数量减少到不损害应用程序的足够数量。
示例
$ free -m
total used free shared buff/cache available
Mem: 385625 307295 40921 4 37408 74865
所以大约 380G 的 RAM,相当大的内存量。现在让我们检查一下考虑到大使用连接数的大潜在分配。
*这里有一点免责声明,虽然这个查询并不完全准确,因此它可能与实际结果不同,但我们可以了解可能要分配的内容,我们可以利用 performance_schema 数据库,但这可能需要启用一些仪器默认禁用:
MySQL
mysql > show global status like 'max_used_connections';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| Max_used_connections | 67 |
+----------------------+-------+
1 row in set (.00 sec)
因此,多使用 67 个连接,我们可以得到:
MySQL
mysql > SELECT ( @@key_buffer_size
-> + @@innodb_buffer_pool_size
-> + 67 * (@@read_buffer_size
-> + @@read_rnd_buffer_size
-> + @@sort_buffer_size
-> + @@join_buffer_size
-> + @@tmp_table_size )) / (1024*1024*1024) AS MAX_MEMORY_GB;
+---------------+
| MAX_MEMORY_GB |
+---------------+
| 316.4434 |
+---------------+
1 row in set (.00 sec)
到目前为止,一切都很好,我们在内存范围内,现在让我们看看innodb_buffer_pool_size有多大,以及它的大小是否合适:
MySQL
mysql > SELECT (@@innodb_buffer_pool_size) / (1024*1024*1024) AS BUFFER_POOL_SIZE;
+------------------+
| BUFFER_POOL_SIZE |
+------------------+
| 310.0000 |
+------------------+
1 row in set (.01 sec)
所以缓冲池是 310G,大约占总内存的 82%,到目前为止,总使用量大约是 84%,剩下大约 60G 的内存没有被使用。好吧,被文件系统缓存使用,终,InnoDB 没有使用它。
好的,现在让我们进入正题,如何正确配置内存以供 MySQL 有效使用。从 pt-mysql-summary 我们知道缓冲池已满:
Shell
Buffer Pool Size | 310.0G
Buffer Pool Fill | 100%
这是否意味着我们需要更多内存?也许吧,所以让我们使用以下命令检查我们知道的实例中有多少磁盘操作,而工作数据集不适合内存(这正是我们增加内存大小的原因):
Shell
mysqladmin -r -i 1 -c 60 extended-status | egrep "Innodb_buffer_pool_read_requests|Innodb_buffer_pool_reads"
| Innodb_buffer_pool_read_requests | 99857480858|
| Innodb_buffer_pool_reads | 598600690 |
| Innodb_buffer_pool_read_requests | 274985 |
| Innodb_buffer_pool_reads | 1602 |
| Innodb_buffer_pool_read_requests | 267139 |
| Innodb_buffer_pool_reads | 1562 |
| Innodb_buffer_pool_read_requests | 270779 |
| Innodb_buffer_pool_reads | 1731 |
| Innodb_buffer_pool_read_requests | 287594 |
| Innodb_buffer_pool_reads | 1567 |
| Innodb_buffer_pool_read_requests | 282786 |
| Innodb_buffer_pool_reads | 1754 |
Innodb_buffer_pool_read_requests:从内存中读取满足的页面(好)
Innodb_buffer_pool_reads:从磁盘读取页面(坏)
您可能会注意到,我们仍然会从磁盘读取一些数据,并且我们希望避免它们,所以让我们将缓冲池大小增加到 340G(总内存的 90%)并再次检查:
Shell
mysqladmin -r -i 1 -c 60 extended-status | egrep "Innodb_buffer_pool_read_requests|Innodb_buffer_pool_reads"
| Innodb_buffer_pool_read_requests | 99937722883 |
| Innodb_buffer_pool_reads | 599056712 |
| Innodb_buffer_pool_read_requests | 293642 |
| Innodb_buffer_pool_reads | 1 |
| Innodb_buffer_pool_read_requests | 296248 |
| Innodb_buffer_pool_reads | |
| Innodb_buffer_pool_read_requests | 294409 |
| Innodb_buffer_pool_reads | |
| Innodb_buffer_pool_read_requests | 296394 |
| Innodb_buffer_pool_reads | 6 |
| Innodb_buffer_pool_read_requests | 303379 |
| Innodb_buffer_pool_reads | |
现在 IO 压力被释放了。
概括
如果您增加服务器的内存大小,您主要需要关注innodb_buffer_pool_size,因为这是关键的调整变量。在大型系统上分配 90% 到 95% 的总可用内存一点也不坏,因为操作系统只需要几 GB 即可正常运行,而更多的内存交换应该足以正常运行。
此外,请检查您需要(和已使用)的大连接数,因为这是导致内存问题的常见错误,如果您需要在打开 1000 个连接的情况下运行,则可能无法分配缓冲池的 90% 内存,并且可能需要一些额外的操作(即,添加代理层或连接池)。
从 MySQL 8 开始,我们有一个名为innodb_dedicated_server的新变量,它将自动计算内存分配。虽然这个变量对于初始方法非常有用,但它可能会在 RAM 超过 4G 的系统中分配不足,因为它设置缓冲池大小 =(检测到的服务器内存 * 0.75),所以在 200G 的服务器中,我们有缓冲池只有 150 个。
结论
垂直扩展是提高性能的简单、快的方法,而且成本更低——但并不神奇。正确调整变量需要分析和理解内存的使用方式。这篇文章重点介绍了调整内存分配时要考虑的基本变量,特别是 innodb_buffer_pool_size 和 max_connections。不需要时不要过度调整,并注意这两者如何影响您的系统。
来自:Linux迷