当前位置: 首页 > news >正文

Oracle 中 open_cursors 参数详解:原理、配置与性能测试

#Oracle #参数 # open_cursors #ORA-01000

在 Oracle 数据库的众多参数中,open_cursors是一个对应用程序性能和资源管理有着重要影响的参数。它直接关系到数据库与应用程序之间游标资源的使用与分配,合理配置open_cursors参数,能够避免应用程序出现游标相关的错误,提升数据库的整体运行效率。本文将深入介绍open_cursors参数,并通过实际测试过程展示其对数据库性能的影响。

一、open_cursors 参数说明

1. 基本概念

open_cursors参数用于设置单个会话中可以同时打开的游标数量上限。游标是 Oracle 数据库处理 SQL 语句的一个重要机制,它为应用程序提供了一种对查询结果集进行逐行处理的方式。当应用程序执行SELECT、INSERT、UPDATE、DELETE等 SQL 语句时,Oracle 会隐式或显式地打开游标,以管理数据的读取和操作。

2. 作用与影响

如果应用程序在一个会话中打开的游标数量超过open_cursors参数设置的值,Oracle 将抛出ORA-01000: maximum open cursors exceeded错误,导致应用程序运行异常。另一方面,open_cursors参数值设置过大,会占用过多的系统资源,增加内存开销,影响数据库的整体性能;设置过小,则可能无法满足应用程序的正常需求,限制应用程序的并发处理能力。因此,根据应用程序的实际需求和数据库负载情况,合理设置open_cursors参数至关重要。

3. 动态调整

open_cursors是一个动态参数,这意味着在数据库运行过程中,可以通过ALTER SYSTEM或ALTER SESSION语句对其进行修改,而无需重启数据库实例。例如,要将全局的open_cursors参数值设置为 1000,可以使用以下语句:

ALTER SYSTEM SET open_cursors = 1000 SCOPE = BOTH;

若只想在当前会话中修改该参数值,则使用:

ALTER SESSION SET open_cursors = 1000;

二、什么是打开的游标

 跟踪一下v$open_cursor底层调用的基表

select view_definition from v$fixed_view_definition where view_name like 'V$OPEN_CURSOR'select SADDR,SID,USER_NAME,ADDRESS,HASH_VALUE,SQL_ID,SQL_TEXT,LAST_SQL_ACTIVE_TIME,SQL_EXEC_ID,CURSOR_TYPE,CHILD_ADDRESS,CON_IDfrom GV$OPEN_CURSORwhere inst_id = USERENV('Instance')select view_definition from v$fixed_view_definition where view_name like 'GV$OPEN_CURSOR';select inst_id,kgllkuse,kgllksnm,user_name,kglhdpar,kglnahsh,kgllksqlid,kglnaobj,kgllkest,decode(kgllkexc, 0, to_number(NULL), kgllkexc),kgllkctp,kgllkhdl,con_idfrom x$kgllkwhere kglhdnsp = 0and kglhdpar != kgllkhdl

x$kgllk是library cache lock相关的基表,那我们可以得到结论:只要SQL上加了library cache lock,就是一个打开的游标。那什么场景下,SQL会加上library cache lock,我们在后面的知识体系中再介绍。

三、游标相关的报错ORA-01000: maximum open cursors exceeded

3.1、报错原因

ORA-01000错误的核心原因是在单个数据库会话中,打开的游标数量超过了open_cursors参数所设定的上限。游标是 Oracle 处理 SQL 语句时用于管理数据操作的重要机制,无论是执行简单的查询语句,还是复杂的事务操作,都会涉及到游标。当应用程序频繁执行 SQL 语句,却没有及时关闭不再使用的游标,就会导致游标不断累积。一旦累积数量突破open_cursors的限制,Oracle 数据库就会抛出ORA-01000错误。

此外,应用程序代码中存在逻辑缺陷,例如在循环中重复打开游标却未正确释放,或者在事务处理过程中异常终止但游标未关闭,也会造成游标资源过度占用,进而触发该错误。同时,若open_cursors参数设置不合理,无法满足应用程序实际的游标使用需求,即使应用程序代码正常,也可能出现此报错。

3.2 报错影响

ORA-01000错误会直接中断应用程序的正常运行。当应用程序执行到引发该错误的 SQL 语句时,会立即停止执行,并将错误信息返回给调用端。这会导致用户操作失败,严重影响业务流程的连续性,降低用户体验。

从数据库层面来看,过多未关闭的游标会占用大量的内存资源,导致数据库内存使用效率下降。如果多个会话同时出现游标超标的情况,还可能引发数据库性能急剧恶化,甚至导致数据库响应缓慢、服务不可用等严重后果。长期积累的未关闭游标还可能造成内存碎片,进一步影响数据库的稳定性和性能。

3.3 故障模拟

1、查看当前的open_cursor参数SYS@pdb1> show parameter open_cursorNAME                                TYPE        VALUE------------------------------------ ----------- ------------------------------open_cursors                        integer    3002、新开一个连接APPS@pdb1> select distinct sid from v$mystat;SID----------4483、打开300个游标,不关闭declaremsql varchar2(2000);mcur number;mstat number;beginfor i in 1..300 loopmcur := dbms_sql.open_cursor;msql := 'select object_id from apps.t1 where object_id='||to_char(i);dbms_sql.parse(mcur,msql,dbms_sql.native);mstat :=dbms_sql.execute(mcur);end loop;end;/4、查看SID=448正在打开的游标SYS@pdb1> select count(1)2    from v$open_cursor t3  where t.sid = '448'4    and t.cursor_type = 'OPEN-RECURSIVE';COUNT(1)----------299

3.4 排查思路

(1)  检查open_cursors参数设置

使用以下 SQL 语句查询当前数据库实例的open_cursors参数值:

SELECT valueFROM v$parameter WHERE name = 'open_cursors';

  对比该参数值与应用程序实际的游标使用需求,判断是否设置过小。若应用程序存在大量并发操作或复杂的 SQL 执行逻辑,可能需要适当增大该参数值。

(2)分析应用程序代码

仔细审查应用程序中涉及数据库操作的代码,重点检查游标打开和关闭的逻辑。查看是否存在循环中重复打开游标却未关闭的情况,或者事务回滚、异常处理时游标未正确释放的问题。对于使用连接池的应用,确保连接池配置合理,连接归还时游标已全部关闭。

(3)监控数据库会话

通过查询v$open_cursor视图,获取当前所有打开的游标信息,找出当前打开游标最多的会话:

SELECT  S.USERNAME, A.VALUE,S.SID, S.SERIAL#FROM V$SESSTAT A, V$STATNAME B, V$SESSION SWHERE A.STATISTIC# = B.STATISTIC#AND S.SID = A.SIDAND B.NAME = 'opened cursors current'order by value desc;

找出游标数量异常多的会话,结合应用程序业务逻辑,判断是否存在不合理的游标使用。

3.5 故障解决方案

解决这个问题,本质就是要关闭掉打开的游标,可以通过以下方法:  

1、退出执行会话的窗口

2、KILL掉会话

1、查看会话打开的cursor数SYS@pdb1> select sid,count(1)from v$open_cursor twhere  t.cursor_type = 'OPEN-RECURSIVE'group by sid;SID  COUNT(1)---------- ----------422          2448        298440        102、查看SID=448的PIDSYS@pdb1> select spid from v$session s ,v$process p where s.paddr=p.addr and sid=448;SPID------------------------248083、kill掉进程[oracle@database ~]$ ps -ef|grep 24808oracle    24808      1  0 09:53 ?        00:00:00 oracleORCLCDB (LOCAL=NO)oracle    24848  7583  0 09:56 pts/2    00:00:00 grep --color=auto 2480[oracle@database ~]$ kill -9 248084、查看会话打开的游标SYS@pdb1> select sid,count(1)2        from v$open_cursor t3      where  t.cursor_type = 'OPEN-RECURSIVE'4      group by sid;SID  COUNT(1)---------- ----------422          2440        10

3、KILL应用端连接进程

3.6 优化方案

1. 调整open_cursors参数

如果确定是参数设置过小导致的错误,可以通过以下语句调整open_cursors参数值:

-- 全局修改ALTER SYSTEM SET open_cursors = [新值] SCOPE = BOTH;-- 仅修改当前会话ALTER SESSION SET open_cursors = [新值];

修改参数值时,需综合考虑数据库服务器的硬件资源和应用程序的实际需求,避免设置过大影响系统性能。可以通过查看OPEN_CURSOR当前最大打开数,获取参考值。

SELECT MAX(A.VALUE) AS HIGHEST_OPEN_CUR, P.VALUE AS MAX_OPEN_CURFROM V$SESSTAT A, V$STATNAME B, V$PARAMETER PWHERE A.STATISTIC# = B.STATISTIC#AND B.NAME = 'opened cursors current'AND P.NAME = 'open_cursors'GROUP BY P.VALUE;

2. 优化应用程序代码

修正应用程序中游标使用的逻辑错误,确保在游标使用完毕后及时关闭。对于复杂的事务处理和循环操作,合理规划游标的打开和关闭时机。例如,在 Java 应用中,使用try-with-resources语句自动关闭游标:

try (Connection connection = DriverManager.getConnection(url, user, password);​Statement statement = connection.createStatement();​ResultSet resultSet = statement.executeQuery("SELECT * FROM employees")) {​while (resultSet.next()) {​// 处理结果集​}​} catch (SQLException e) {​e.printStackTrace();​}

3. 加强数据库监控

建立完善的数据库监控机制,定期检查open_cursors参数的使用情况和游标资源占用情况。通过设置告警阈值,当游标数量接近或超过open_cursors参数值时,及时发出告警,以便运维人员提前采取措施,避免ORA-01000错误的发生。

四、 总结

通过对比不同的使用场景,可以发现:

  • 当使用默认参数值或参数值设置较小时,测试程序在打开一定数量游标后,会出现ORA-01000错误,导致程序无法正常执行,影响应用程序的稳定性。
  • 随着open_cursors参数值的增大,程序能够顺利执行完所有游标操作,执行时间可能会有所缩短,因为减少了因游标数量限制导致的错误处理和重新连接等额外开销。但同时,数据库的内存使用量会相应增加,因为更多的游标需要占用内存资源。
  • 在超出参数值测试场景中,明确验证了open_cursors参数对游标数量的限制作用,当游标数量超过设置值时,会及时抛出错误,提醒开发人员需要调整参数或优化应用程序中游标的使用。

综上所述,open_cursors参数在 Oracle 数据库中起着关键的作用,合理配置该参数能够有效提升应用程序的性能和稳定性。在实际应用中,需要根据应用程序的并发量、业务逻辑以及数据库的硬件资源情况,综合考虑并动态调整open_cursors参数值,以达到最佳的运行效果。


🚀 更多数据库干货,欢迎关注【安呀智数据坊】

如果你觉得这篇文章对你有帮助,欢迎点赞 👍、收藏 ⭐ 和留言 💬 交流,让我知道你还想了解哪些数据库知识!

📬 想系统学习更多数据库实战案例与技术指南?

  • 📊 实战项目分享

  • 📚 技术原理讲解

  • 🧠 数据库架构思维

  • 🛠 工具推荐与实用技巧

立即关注,持续更新中 👇

http://www.xdnf.cn/news/537463.html

相关文章:

  • 一键无损批量压缩图片 保留高清细节 开源免费!支持 10 + 格式转换
  • HashMap 的特点及应用场景
  • GraphQL 接口设计
  • SRS流媒体服务器(6)源码分析之推流篇
  • 2025.05.19【Barplot】柱状图的多样性绘制
  • Linux句柄数过多问题排查
  • stm32如何触摸屏设置显示按钮
  • c#将json字符串转换为对象数组
  • Linux-进程信号
  • Python 与 Java 在 Web 开发中的深度对比:从语言特性到生态选型
  • GPU状态监控
  • MPCount: 人群计数的单域泛化
  • 【成品设计】基于 STM32 的智能鞋柜系统
  • TransmittableThreadLocal实现上下文传递-笔记
  • 「HHT(希尔伯特黄变换)——ECG信号处理-第十三课」2025年5月19日
  • 院校机试刷题第七天:1828西交-矩阵相加、1822计算圆周率、1823学生成绩排序
  • 基于PetaLinux的Zynq PS应用自启动全攻略
  • 开发指南116-font-size: 0的使用
  • 深入解析 Oracle session_cached_cursors 参数及性能对比实验
  • python动漫论坛管理系统
  • ubuntu open shh9.9安装
  • W3电力线载波通信技术
  • 物流项目第一期(登录业务)
  • 40亿非负整数中找到出现两次的数和所有数的中位数
  • 技术决策缺乏团队参与,如何增强执行力?
  • 修改样式还能影响功能?是的!
  • 掌握Python编程:从C++/C#/Java开发者到AI与医学影像开发专家
  • C#编写软件添加菜单栏
  • 2 sys库
  • 陀螺匠部门默认角色怎么用