首批通过分布式安全可靠测评,为关键业务系统打造
OceanBase 数据库 V3.x 版本中 Oracle 租户执行包含 regexp_replace 复杂表达式时 SQL 报错 -4013 的原因和解决方法
更新时间:2026-05-19 08:21
问题现象
OceanBase 数据库 V3.x 版本中 Oracle 租户执行包含 regexp_replace 复杂表达式 SQL 报错 -4013。
obclient [SYS]> select regexp_replace('JMN1L~1000~5', '^([^~]+)~(\d+)|(.*)', '\2') from dual;
ORA-00600: internal error code, arguments: -4013, No memory or reach tenant memory limit
关键日志信息。
observer.log.20240815094436:[2024-08-15 09:42:02.011150] WARN [SQL.ENG] calc (ob_expr_regexp_replace.cpp:407) [86918][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=5] [dc=0] fail to replace substr(ret=-4013, text=JMN1L~1000~5, replacement_string=\2)
observer.log.20240815094436:[2024-08-15 09:42:02.011159] WARN [SQL.ENG] eval_regexp_replace (ob_expr_regexp_replace.cpp:510) [86918][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=7] [dc=0] calc failed(ret=-4013)
observer.log.20240815094436:[2024-08-15 09:42:02.011594] ERROR [LIB] pre_process_replace_str (ob_expr_regexp_context.cpp:1039) [86918][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=10] [dc=0] alloc memory failed.(real_buf=NULL, ret=-4013) BACKTRACE:0xfd5bd00 0x584489f 0x5885c1f 0x588585f 0x5885718 0x6129a14 0xdb5be0d 0xdb5a8f9 0xdb58c67 0xdb573da 0xdb6f0ae 0xdb70b69 0x56a9881 0x5631e29 0x5631ca4 0x5631a2e 0x56316ac 0xbd0b5fd 0x5630084 0x562ac63 0x56288ff 0x5626a7e 0xc063bf1 0x5625c97 0xc061381 0x56218f6 0xc0618f7 0xfc30873 0xfc306cf 0xfed3a8f
observer.log.20240815094436:[2024-08-15 09:42:02.011969] INFO [SERVER] ob_query_retry_ctrl.cpp:579 [86918][0][xxxxx-xxxxx-xxxxx-xxxxx] [lt=8] [dc=0] check if need retry(client_ret=-4013, err=-4013, retry_type_=0, retry_times=1, multi_stmt_item={is_part_of_multi_stmt:true, seq_num:0, sql:"select regexp_replace('JMN1L~1000~5', '^([^~]+)~(\d+)|(.*)', '\2') from dual"})
问题原因
当前报错为产品缺陷,对 JMN1L~1000~5 字符串,pattern 匹配到了 (.*),所以 \1 和 \2 都是空串,只有 \3 是有值的,在构造占位符对应的字符串的时候,\2 分配了空指针,内部报了 -4013。
问题的风险及影响
SQL 执行报错。
影响租户
影响 OceanBase 数据库中的 SYS 租户和 Oracle 租户以及 MySQL 租户。
适用版本
OceanBase 数据库 V3.x 版本。
解决方法及规避方式
只要业务的字段都是这种值 JMN1L~1000~5 对任意字符 按照 ~ 分割拆成 3 段。
select regexp_replace('JMN1L~1000~5', '^([^~]+)~(\d+)(.*)', '\1') from dual;
select regexp_replace('JMN1L~1000~5', '^([^~]+)~(\d+)(.*)', '\2') from dual;
select regexp_replace('JMN1L~1000~5', '^([^|]+)~(\d+)~(\d+)|(.)', '\3') from dual;