最开始我会想到调整 innodb_buffer_pool_size 是因为我发现数据库上的 swap 非常高。经过排查我发现是因为 innodb_buffer_pool_size 设置得偏大了。在内存不足的时候,操作系统就会触发 swap。 解决思路自然是调小一点,但是这样做要小心对业务的影响。实际上 innodb_buffer_pool_size 是逐步调整的,最后调整到原本数值的 70%,swap 就大幅减少了,而且查询性能也没什么变化。
你还可以进一步说明另外一个相关的参数 innodb_buffer_pool_instances。从图里你可以看到,要是整个 MySQL InnoDB 引擎内部只有一个缓冲池,所有查询都访问它,那么并发竞争会十分厉害。
在这种情况下,可以考虑启动多个缓冲池实例,具体多少个就由 innodb_buffer_pool_instances 这个参数指定。显然这个数字越大,并发竞争就越小。
可惜 MySQL 有一些额外的限制,它要求在 innodb_buffer_pool_instances 大于 1 的情况下,innodb_buffer_pool_size 不能小于 1G。一般我建议在 8G 以内设置成 2 就可以,如果大于 8G 那么可以设置成 4。
可以把 innodb_buffer_pool_size 和 innodb_buffer_pool_instances 放到一起说。
在解决了 innodb_buffer_pool_size 的 Bug 之后,我负责的系统数据库的相关设置,又发现了一个问题。我们有一个核心数据库,innodb_buffer_pool_size 超过了 8G,但是 innodb_buffer_pool_instances 居然还保持着 1,这显然是不合理的。所以这个我就把它调整成了 4,减少数据库 buffer pool 的并发竞争。