MySQL存储过程中JSON_TABLE首次运行正常,后续执行失效求助
问题
在MySQL 8.0.12环境下,两个包含JSON_TABLE的存储过程出现异常:首次执行结果正常,但后续执行返回null且无任何报错;重新编辑并保存存储过程后,首次执行又恢复正常,但后续执行依旧失效。将存储过程内的SQL语句直接放到查询窗口中,却可以反复正常运行,已确认问题与JSON_TABLE的使用相关。
涉及的存储过程代码如下:
CREATE DEFINER=`username`@`%` PROCEDURE `sp_filter_values_add`(_dashboard_filter_id int(11)) BEGIN insert into us_ui_dashboard_filter_values (dashboard_filter_id, section_id, section_item_id, filter_value, filter_value_text ) select dt.dashboard_filter_id, x1.section_id, x1.section_item_id, x1.filter_value, x1.filter_value_text from us_ui_dashboard_filter dt, json_table( dt.filter_json, '$[*]' columns ( section_id int(11) PATH '$.section_id', section_item_id int(11) PATH '$.section_item_id', filter_value int(11) PATH '$.filter_value', filter_value_text int(11) PATH '$.filter_value_text' ) ) x1 WHERE dt.dashboard_filter_id = _dashboard_filter_id; END
解决方向与替代方案
1. 强制JSON重新解析,绕过缓存
修改JSON_TABLE的输入参数,对dt.filter_json做显式的JSON类型转换,避免优化器缓存旧的解析结果:
json_table( CAST(dt.filter_json AS JSON), '$[*]' columns ( section_id int(11) PATH '$.section_id', section_item_id int(11) PATH '$.section_item_id', filter_value int(11) PATH '$.filter_value', filter_value_text int(11) PATH '$.filter_value_text' ) ) x1
2. 关闭派生表合并优化
在存储过程的BEGIN之后添加语句,临时关闭当前会话的派生表合并优化,防止优化器错误缓存JSON_TABLE的执行逻辑:
SET SESSION optimizer_switch='derived_merge=off';
注意:该设置仅对当前会话有效,不会影响全局配置。
3. 升级MySQL版本
MySQL 8.0.12属于早期版本,存在JSON_TABLE在存储过程中执行计划缓存的已知bug,后续版本(如8.0.18及以上)已修复该问题。升级到稳定的高版本可彻底解决此异常。
4. 替代方案:拆分逻辑
如果暂时无法升级或修改优化器配置,可以将JSON_TABLE的解析逻辑拆分为临时表操作:
- 先将目标行的
filter_json字段值取出,存入变量 - 再用
JSON_TABLE解析变量中的JSON数据,插入目标表
示例代码:
CREATE DEFINER=`username`@`%` PROCEDURE `sp_filter_values_add`(_dashboard_filter_id int(11)) BEGIN DECLARE _filter_json JSON; -- 取出目标JSON数据 SELECT filter_json INTO _filter_json FROM us_ui_dashboard_filter WHERE dashboard_filter_id = _dashboard_filter_id; insert into us_ui_dashboard_filter_values (dashboard_filter_id, section_id, section_item_id, filter_value, filter_value_text ) select _dashboard_filter_id, x1.section_id, x1.section_item_id, x1.filter_value, x1.filter_value_text from json_table( _filter_json, '$[*]' columns ( section_id int(11) PATH '$.section_id', section_item_id int(11) PATH '$.section_item_id', filter_value int(11) PATH '$.filter_value', filter_value_text int(11) PATH '$.filter_value_text' ) ) x1; END
内容的提问来源于stack exchange,提问作者Lexius
相关产品推荐
相关产品推荐

