【问题分类】资源管理 / 内存泄露风险

【关键词】YAS-00103、stmt未关闭、open cursor、share pool、内存耗尽

一、问题现象

在某客户业务中,系统运行过程中频繁报出如下错误:

YAS-00103 no free block in sql main pool part 0
YAS-00105 out of memory to allocate hash table of size = 256

报错时伴随业务功能异常、部分SQL无法正常执行,严重影响使用。

二、影响版本

该问题出现在 YashanDB 22.2.4.1 版本中。

三、问题影响与风险

直接影响数据库的 SQL 执行能力,可能导致大量 SQL 报错无法下发;

长期不处理,可能拖垮 share pool,影响其他正常连接。
image.png

四、问题根因分析

现象表现:

错误提示表明 SQL主内存池空间不足,即“sql main pool part 0”无可用块;

根本原因在于:业务代码中创建 stmt(prepare/execute)后未调用 close 释放资源。

背景知识:

在 YashanDB 中,每条 SQL 在执行时会生成一个 stmt 对象,生命周期如下:


typedef enum EnAnlStmtStatus {
STMT_STATUS_IDLE = 0.     // 已执行但未释放
STMT_STATUS_PREPARE = 1.
STMT_STATUS_EXECUTE = 2.
STMT_STATUS_FETCH = 3.
STMT_STATUS_FREE = 4      // 已释放,可复用
} AnlStmtStatus;

当 stmt 执行完毕但未显式 close 时,它就会停留在 idle 状态,无法自动复用。

此外:

cursor 不会在 SQL 执行完后销毁;

cursor 生命周期 = session 生命周期;

每个 session 的最大 open cursor 数由 OPEN_CURSORS 控制;

所有未释放 stmt 长期占用 share_pool 空间,最终导致 pool 空间枯竭。

五、问题复现方式(示例)

1.连续 prepare/execute 多条 SQL,不执行 stmt.close;

2.session 不断保持连接,cursor 不释放;

3.触发 SQL pool 内存耗尽,产生 YAS-00103 报错。

六、定位方法与排查建议

查看资源使用情况:

v$global_mpool:查看 SQL Pool 使用情况;

v$open_cursor:查看 session 当前所有打开 stmt 状态;

观察是否存在大量 STMT_STATUS_IDLE 的游标未释放。

配置参数确认:

OPEN_CURSORS:单 session 可打开最大 cursor 数;

SHARE_POOL_SIZE:若太小,内存更容易被锁死资源占满。

七、解决与规避建议

彻底解决:在应用中显式调用stmt.close()释放资源
示例:

Statement stmt = conn.prepareStatement(sql);
try {
stmt.execute();
} finally {
stmt.close();  // 非常关键
}

临时规避: 调高 SHARE_POOL_SIZE 参数,扩大内存缓冲; 示例命令:


ALTER SYSTEM SET SHARE_POOL_SIZE = xxx SCOPE = SPFILE;

最后防线:

如果无法控制应用层,可通过定期断开 idle session 来释放资源(如启用连接池 maxIdleTime);

或监控 v$open_cursor 状态,定期告警处理未释放资源。

八、经验总结

忘记关闭 stmt,是高频 SQL 报错与内存耗尽的重要诱因;

应用层规范编码、数据库端资源参数配置、运维监控三者需协同;

遇到类似 YAS-00103 报错,应优先排查 cursor 未释放情况,而非简单调大内存。


数据库砖家
1 声望0 粉丝