---
title: 编组
description: 了解OceanBase数据库在实际应用中关于查询列包含 UDF 导致 OMA 回放 SQL 执行缓慢的排查与优化方案相关的常见问题和使用技巧，帮助您快速解决查询列包含 UDF 导致 OMA 回放 SQL 执行缓慢的排查与优化方案的难题。
image: https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*OSPzQ6GUQF4AAAAAQHAAAAgAeiGDAQ/original
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# 查询列包含 UDF 导致 OMA 回放 SQL 执行缓慢的排查与优化方案

更新时间：2026-08-25 06:51

内容类型：Troubleshoot  

## 问题现象

在 OceanBase 数据库进行 OMA（流量回放/压测）期间，包含自定义 UDF（如解密函数）的 SQL 执行耗时显著上升（正常约 10 ms，带 UDF 升至 100 ms 甚至数秒）。高并发场景下引发严重的队列积压与重试放大效应，同时伴随客户端接收结果集延迟、系统日志被异常信息频繁打印打满等现象。 问题 SQL 中包含形如 `aes_decypt(xx) AS xx` 的查询，即查询列包含自定义 UDF。 对应执行的日志中反复出现以下告警信息：

```text
WDIAG decode ... [errcode=-4002] REACH SYSLOG RATE LIMIT [bandwidth]
WDIAG [PL] execute ... [errcode=-4002] Unhandled exception has occurred in PL (ret=-4002)
WDIAG [SQL.ENG] eval_udf ... [errcode=-4002] fail to execute udf (ret=-4002, package_id=310184)
WDIAG [STORAGE] reset ... [errcode=-4389] guard used too much time (guard_used_us=25044556)

```

从日志可见：PL 层出现未处理异常（errcode=-4002），UDF 执行失败（package_id=310184），单次执行耗时过长（约 25 秒），且异常信息频繁打印触发日志限流（REACH SYSLOG RATE LIMIT）。 日志中的关键信息如下：

```text
expr_type:"T_FUN_UDF"              -- UDF 类型，不是系统函数
expr_name:"user_define_function"   -- 明确为"用户自定义函数"
package_id=310184                  -- 属于某个 PL/SQL package

```

## 关键诊断信息

### 触发条件

- 查询结果列包含自定义 PL/SQL UDF（如解密函数）。
 - OMA 回放/压测等高并发场景下执行包含该 UDF 的 SQL。

### 事前巡检

- 检查业务 SQL 的查询列中是否包含用户自定义函数，尤其是高并发查询场景。
 - 可通过以下 SQL 确认函数是否为用户创建（示例以 AES_DECRYPT 为例，请替换为实际函数名；如函数属于指定用户，可增加 owner 过滤条件）：

```sql
-- 查看 AES_DECRYPT 是否为用户创建的函数/包
SELECT object_name, object_type, status
FROM cdb_objects
WHERE object_name = 'AES_DECRYPT';
-- 查看函数源码
SELECT text
FROM cdb_source
WHERE name = 'AES_DECRYPT'
ORDER BY line;
-- 或查看日志中 package_id 对应的 package 源码（将 310184 替换为日志中实际打印的 package_id）
SELECT object_name, object_type
FROM cdb_objects
WHERE object_id = 310184;

```

### 事后诊断

- `sql_audit` 视图中的 `PLSQL_EXEC_TIME` 字段值与 SQL 实际执行耗时基本一致，可作为定位 PL/UDF 执行耗时的关键诊断指标。
 - 业务高峰期 SQL 执行慢时，重试次数显著增高，且单次执行时间超过 5 秒即被纳入大查询队列。
 - 客户端（如 OMA）可能出现长时间（数十秒）未读取发送缓冲区数据（如 6.7 MB）的情况，导致接收端阻塞。
 - 修复前 Syslog/WDIAG 日志因 UDF 解码失败频繁报错被大量打满；修复后日志恢复平稳。

## 问题原因

该问题由自定义 UDF 实现逻辑缺陷引发，并非数据库内核缺陷。具体原因如下：

1. **异常处理机制不当**：UDF 内部调用底层编码/解码函数时抛出异常（如 -4002），但使用 `EXCEPTION WHEN OTHERS` 捕获异常后未及时中断，而是继续处理大量数据行后才抛出未处理异常，异常最终冒泡至 SQL 层，导致整批语句执行失败，而非单行跳过。
 2. **重试与队列放大效应**：单次执行因异常处理变慢（超过 5 秒）后被放入大查询队列，反复重试进一步放大执行时间。
 3. **客户端消费瓶颈**：OMA 回放期间模拟高并发压测，数据库侧返回的大体积结果集未能被客户端及时消费，TCP 缓冲区堆积导致客户端成为最终性能瓶颈。 此问题本质是用户自定义 UDF 本身存在问题，导致执行性能不优。 此外，内置函数与 PL/SQL UDF 的执行方式存在差异：

- 内置函数（如 MySQL 兼容模式的 AES_DECRYPT）：由数据库内核直接实现，单行执行耗时微秒级，无异常处理开销，无上下文切换开销。
 - PL/SQL UDF（Oracle 兼容模式，当前场景）：需经过 PL/SQL 解释执行，单行执行耗时毫秒级，比内置函数慢 100~1000 倍；每次调用存在上下文初始化开销，异常处理（`EXCEPTION WHEN OTHERS`）有额外开销，每行数据都要经历完整的 PL/SQL 调用栈。

## 问题的风险及影响

SQL 执行性能严重下降，高并发下引发队列积压与重试风暴；异常处理不当可能导致单条脏数据引发整批 SQL 执行失败；系统日志被异常信息频繁打印，占用磁盘 IO 并干扰日常监控与故障排查。

## 影响租户

| sys | MySQL | Oracle |
| --- | --- | --- |
| NO | NO | YES |

## 影响版本

| 影响版本 |
| --- |
| 所有版本 |

## 解决方法

修正 UDF 的定义与实现逻辑，确保在调用底层解码函数前清理输入数据中的非法字符或换行符（如使用 `REPLACE` 函数），避免异常抛出导致执行阻塞或失败。

## 规避方式

- 修正 UDF 的定义，完善异常捕获与返回逻辑，防止异常冒泡至 SQL 层。
 - 架构层面建议将加密/解密逻辑迁移至应用侧实现，或在应用与数据库之间引入缓存机制以降低数据库 CPU 消耗。
 - 合理划分流量路由，高并发业务查询流量优先走主副本，数据迁移等后台流量可路由至 WEAK 读从副本。
 - 针对大结果集并发返回场景，可适当调大客户端 TCP 接收缓冲区参数，提升结果集消费能力。

上一篇

[PDML Insert 不支持 Interval 分区问题分析](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000006802570)

下一篇

[[HG] 带局部索引的表 add/drop/truncate 分区后 DML 出现 4377](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000006830282) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
