MySQL会话连接数消耗内存分析

关于连接数消耗内存情况

FROM DEEPSEEK

在 MySQL 中,每个单独的空闲连接所消耗的内存量取决于多个因素,包括连接的线程栈大小(由 `thread_stack` 参数设置)和其他每个连接的缓冲区。根据测试结果来看,对于空闲连接的内存消耗并没有一个固定的数值,因为它会根据连接的活跃状态和执行的查询类型而变化。然而,对于内存规划目的,推荐平均每个连接计划约10MB内存。

线程栈(Thread Stack)是操作系统为每个线程分配的一段内存区域,用于存储线程的局部变量、函数调用信息、返回地址等。在多线程环境中,每个线程都有自己的线程栈,以确保线程之间数据隔离,防止数据竞争和相互干扰。

线程栈的大小:

线程栈的大小对应用程序的性能和资源使用有重要影响。栈太小可能导致栈溢出(Stack Overflow),而栈太大则可能导致内存浪费。

  • 栈溢出:如果线程调用的函数太深或局部变量太大,可能会超出栈的限制,导致栈溢出错误。
    • 程序崩溃:当线程栈溢出时,程序可能会崩溃,导致正在执行的数据库操作失败。
    • 数据不一致:如果栈溢出发生在事务处理过程中,可能会导致数据不一致,因为事务可能无法正确提交或回滚。
    • 资源泄露:栈溢出可能导致资源未能正确释放,从而引发内存泄露或其他资源管理问题。
  • 内存浪费:如果栈大小设置得过大,会浪费内存资源,尤其是在创建大量线程的情况下。

MySQL中的线程栈:

在 MySQL 中,可以通过配置参数 thread_stack 来设置线程栈的大小。这个参数影响 MySQL 服务器为每个新线程分配的内存量。MySQL 5.6 之前的版本中,thread_stack 的默认值通常是 128KB,而在 MySQL 5.7 及更高版本中,这个值增加到了 1MB。

此外,每个 MySQL 连接需要一定量的内存来维护连接状态、缓存查询结果和执行计划等,这个内存量相对较小,可能在几十KB到几百KB之间。对于连接池中的空闲连接,它们会占用一定的内存,但这个内存通常远小于活跃连接时的内存消耗。连接池可以显著减少创建和销毁连接的开销,从而提高数据库交互的效率。

总的来说,空闲连接的内存消耗相对较小,但随着连接数量的增加,累积的内存消耗可能会变得显著。因此,合理地管理数据库连接,例如通过使用连接池技术,对于优化数据库性能和资源使用非常重要。

MySQL8.0.28新特性

MySQL 8.0.28开始,新增一个特性,支持监控统计并限制各个连接(会话)的内存消耗,避免大量用户连接因为执行垃圾SQL消耗过多内存,造成可能被OOM kill的风险。

首先,需要先设置系统选项 global_connection_memory_tracking = 1,之后可以通过系统状态变量 Global_connection_memory 查看当前所有连接消耗的内存总量

相关参数介绍

global_connection_memory_tracking

Global_connection_memory

connection_memory_chunk_size

connection_memory_limit

官方文档:

https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html

问题分析

开源 MySQL8.0.37 开启global_connection_memory_tracking参数

当前有3个连接存在,共消耗内存约1096KB

可以看到当新增一个空闲的连接,内存大概增加了8.05KB左右

并发测试:

待补充.....

可以调整每个会话连接可使用内存上限,由选项 connection_memory_limit 定义其限制,默认值及最大值都是 18446744073709551615,这个默认值太大了,等同于没有限制。

设置connection_memory_limit =209715即2MB

然后调用存储过程插入数据时会发现当前会话超出连接内存限制2097152字节,关闭连接

(4082, 'Connection closed. Connection memory limit 2097152 bytes exceeded. Consumed 2563352 bytes.')

除了上面提到的根据Global_connection_memory参数查看外,我们也可以启用performance_schema然后对线程消耗的内存的分析

SELECT t.PROCESSLIST_ID,
       t.PROCESSLIST_INFO,
       m.EVENT_NAME,
       m.CURRENT_NUMBER_OF_BYTES_USED / 1024 / 1024 AS MB_used
FROM   performance_schema.memory_summary_by_thread_by_event_name m
JOIN   performance_schema.threads t USING (THREAD_ID)
ORDER  BY MB_used DESC
LIMIT  10;

可以看到上面的这个DML消耗了大概2.5G的内存

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值