MySQL/MariaDB C API复用预编译语句重复执行性能下降问题咨询
问题原因
- 结果集资源累积泄漏:最初的复用逻辑中,fetch完所有行后没有主动清理预编译语句的执行上下文,多次执行后服务端累积的游标、临时表、执行计划引用等资源无法释放,最终导致请求阻塞挂死。单独添加
mysql_stmt_free_result或mysql_stmt_reset未生效,大概率是调用顺序不对,没有完全清除上一次执行的残留状态。而每次循环重建预编译语句的逻辑不会触发问题,是因为mysql_stmt_close会自动释放该语句关联的所有服务端、客户端资源,不会出现资源累积的情况。 - 特定版本的已知bug:你使用的MariaDB 10.5.10和mariadb-connector 3.1.13存在多个和复杂查询(含多CTE、窗口函数)预编译语句复用相关的底层bug:服务端执行计划缓存的引用计数异常,多次复用后会触发锁等待或内存泄漏,最终导致请求无限挂起,该问题在后续小版本中已经得到修复。
可行解决方案
- 方案1:修正预编译语句复用逻辑
每次循环的fetch结束后,按顺序执行以下操作清理状态即可正常复用:
同时建议在// 先释放服务端未读取的所有结果集资源 mysql_stmt_free_result(statement); // 重置语句执行状态,清除上一次执行的所有残留上下文 mysql_stmt_reset(statement);mysql_stmt_execute之后立刻调用mysql_stmt_store_result(statement),将结果集一次性拉取到客户端,进一步减少服务端资源占用。 - 方案2:升级组件版本
升级MariaDB Server到10.5.17及以上稳定版,同步升级mariadb-connector-c到3.3.5及以上版本,直接修复底层bug,即可正常享受预编译语句复用的性能优势。 - 方案3:临时兼容方案(无法升级版本时使用)
保留当前每次循环重建销毁预编译语句的逻辑,同时在MariaDB配置文件中开启服务端预编译语句缓存:
开启后服务端会自动缓存常用的预编译语句,重建语句时不会重复解析SQL,性能和复用预编译语句基本一致,同时可以避开版本bug。[mysqld] stmt_cache_size = 256 # 可根据业务并发量调整大小
内容的提问来源于stack exchange,提问作者1653020
相关产品推荐
相关产品推荐

