如何排查并解决MySQL存储过程中因大型游标导致的内存溢出报错问题?
- 内容介绍
- 文章标签
- 相关推荐
本文共计958个文字,预计阅读时间需要4分钟。
执行包含大量游标的存储过程时,MySQL 进程、RSS 内存持续上涨、响应变慢,最终可能被系统的 OOM Killer 杀死。执行杀进程命令后,如 `mesg` 显示类似 `Kill process 12345 (mysqld) score 921`;但执行 `SHOW STATUS` 后,`Innodb_buffer_pool_reads` 并不高,表明这不是缓冲池问题——实际上,往往是游标背后未释放的 `sp_head::main_mem_root` 内存块。
为什么游标会吃光内存:sp_head 和 mem_root 的隐式累积
MySQL 每次执行存储过程(含触发器、函数、事件),都会为该实例分配一个 sp_head 对象,其内部用 main_mem_root 管理所有临时内存(包括游标遍历时的行缓存、临时表、表达式求值栈)。关键点在于:这个内存块在存储过程退出前不会释放,且不会被 innodb_buffer_pool_size 限制。
本文共计958个文字,预计阅读时间需要4分钟。
执行包含大量游标的存储过程时,MySQL 进程、RSS 内存持续上涨、响应变慢,最终可能被系统的 OOM Killer 杀死。执行杀进程命令后,如 `mesg` 显示类似 `Kill process 12345 (mysqld) score 921`;但执行 `SHOW STATUS` 后,`Innodb_buffer_pool_reads` 并不高,表明这不是缓冲池问题——实际上,往往是游标背后未释放的 `sp_head::main_mem_root` 内存块。
为什么游标会吃光内存:sp_head 和 mem_root 的隐式累积
MySQL 每次执行存储过程(含触发器、函数、事件),都会为该实例分配一个 sp_head 对象,其内部用 main_mem_root 管理所有临时内存(包括游标遍历时的行缓存、临时表、表达式求值栈)。关键点在于:这个内存块在存储过程退出前不会释放,且不会被 innodb_buffer_pool_size 限制。

