我们有一个运行 MariaDB 的容器,以及主机上其他一些小容器。Mysql 容器分配了 21G 内存(总共 32G),以及一些其他参数,docker-compose 中的以下命令:
db:
command:
- --innodb_buffer_pool_size=4294967296
- --query_cache_size=268435456
- --tmp_table_size=1073741824
- --max_heap_table_size=1073741824
- --table_open_cache=20000
- --max_connections=1000
- --performance_schema
mem_limit: 21g
我们遇到的问题是,mysql 容器在某些常规备份操作(即命令)期间内存不足mysqldump
,并且容器崩溃。
基本上,容器的内存使用量在大约一周的使用时间内会上升到 21G,并且我认为如果我们不启动任何“大”操作,它就可以保持在那里,但是如果mysqldump
在转储过程中的某个时刻启动了一个命令,它就会超过分配的限制,并且崩溃(当我们在本周早些时候没有达到内存使用量的约 95% 时,它不会崩溃)。
我不明白为什么 MySQL 不能更好地管理它的内存并释放一些内存来启动它需要执行的新命令?
我们尝试将mysqldump
命令放入不同的容器中,以尝试“隔离”这个大操作,但这似乎并没有改变任何东西,大部分工作仍然由 Mysql 容器完成,当另一个容器执行转储时,它最终崩溃。
我们应该检查什么?我们的设置是否完全不对劲?我们在运行 mysqltuner.pl 后设置了它们,如果您认为问题就出在这里,我可以重新运行一次。
我们有大约 700 个数据库,每个数据库大约有 40 个表,平均大约有 10 个同时的 mysql 连接,高峰时有 30 或 50 个。数据库的大小在 10Mb 到 200Mb 之间。
任何帮助都值得感激,谢谢!
答案1
mysqldump
使用该选项运行--quick
。
默认情况下,mysqldump 会尝试一次性转储整个表,这意味着它必须将整个表加载到内存中,当内存受限时mysqldump
可能会失败。该--quick
选项将切换到按行转储,这会稍微慢一些,并且转储文件会稍微大一些,但占用的内存要少得多。
不,我不知道他们为什么命名这个选项--quick
。
答案2
Percona 有一篇文章可能会有所帮助:
https://www.percona.com/blog/2016/05/03/best-practices-for-configuring-optimal-mysql-memory-usage/
这段话似乎部分相关:
操作系统配置的下一件事是设置内存不足杀手。您可能在内核日志文件中看到过这样的消息:
4 月 24 日 02:43:18 db01 内核:内存不足:终止进程 22211 (mysqld) 得分 986 或牺牲子进程
当 MySQL 本身出现故障时,这样做是相当合理的。但是,真正的问题也可能是您正在运行的一些批处理活动:脚本、备份等。在这种情况下,如果系统内存不足,您可能希望终止这些进程,而不是 MySQL。
为了使 MySQL 不太可能被 OOM 终止程序终止,您可以调整行为以使 MySQL 不太受欢迎,方法如下:
echo ‘-800’ > /proc/$(pidof mysqld)/oom_score_adj
这将使得 Linux 内核优先杀死其他内存消耗大户。
========================================================================
显然,您希望优先处理 mysqldump 操作,但如果有其他进程正在使用内存,您可以终止任何您认为多余的进程,并赋予其更高的终止优先级。
我不确定您是如何编写转储脚本的。我认为将转储分成更小的批处理组(表/数据库集)可能会有所帮助,以帮助防止内存过高。这只是一些想法。
答案3
如果你不想给 mysql 分配更多内存,你可以尝试设置复制服务器并从那里执行 mysqldump,问题是当你的服务器有负载时 mysqldump 是有风险的。请查看与性能相关的参数,这也可能有帮助https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html#mysqldump-performance-options
希望这会有所帮助。