MySQL单查询中多次调用存储过程异常 单独调用正常
MySQL单查询多次调用存储过程异常问题
问题表现
同一段包含多条CALL语句调用同一存储过程的SQL,放在单条查询中批量执行时报错,将每条CALL语句拆分单独执行时全部运行正常。
复现代码如下:
CALL DATA_PROCEDURE('text1', 'text2', 1); CALL DATA_PROCEDURE('text3', 'text4', 2); CALL DATA_PROCEDURE('text5', 'text6', 3); CALL DATA_PROCEDURE('text7', 'text8', 4);
常见触发原因及修复方案
客户端/驱动未开启多语句执行支持
绝大多数MySQL连接驱动、可视化客户端默认禁止单次请求发送多条SQL语句,直接拼接多条CALL会在解析阶段直接被拦截,和存储过程本身逻辑无关。
修复方式:- JDBC连接在URL中添加
allowMultiQueries=true参数开启多语句支持 - 可视化客户端在设置中开启「允许多语句执行」选项
- 原生mysql命令行执行时不要将多条语句拼接为单个字符串传入
-e参数
- JDBC连接在URL中添加
前次调用的结果集未完全消费
如果存储过程返回结果集,单次连接上下文中必须完整拉取前一次CALL返回的所有结果集,才能执行下一条SQL,否则会抛出Commands out of sync; you can't run this command now错误。单独执行时每次调用完成后连接上下文会被重置,不会触发该问题。
修复方式:- 清理存储过程中不需要对外返回的
SELECT语句,避免产生多余结果集 - 代码侧调用时,每次
CALL执行完成后必须遍历消费完所有返回的结果集,再发起下一次调用
- 清理存储过程中不需要对外返回的
存储过程上下文状态残留
如果存储过程内部使用了临时表、手动控制事务,批量执行时前一次调用产生的临时表、未提交的事务会残留在会话中,和后一次调用的逻辑产生冲突;单独执行时自动提交机制会清理会话状态,不会触发冲突。
修复方式:- 存储过程中使用临时表前,先执行
DROP TEMPORARY TABLE IF EXISTS 临时表名清理残留 - 存储过程内手动开启的事务,必须保证所有逻辑分支都有对应的
COMMIT/ROLLBACK,不要遗留未结束的事务。
- 存储过程中使用临时表前,先执行
内容的提问来源于stack exchange,提问作者Bartosz Banasiak
相关产品推荐
相关产品推荐

