写点什么

YashanDB 知识库|SQL 语句报 YAS-00103 是因为忘了 close?

作者:数据库砖家
  • 2025-04-21
    广东
  • 本文字数:1162 字

    阅读完需:约 4 分钟

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

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

一、问题现象

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

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

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

二、影响版本

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

三、问题影响与风险

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

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

四、问题根因分析

现象表现:

错误提示表明 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 未释放情况,而非简单调大内存。

用户头像

还未添加个人签名 2025-04-09 加入

还未添加个人简介

评论

发布
暂无评论
YashanDB知识库|SQL语句报 YAS-00103 是因为忘了 close?_数据库·_数据库砖家_InfoQ写作社区