`
asdic
  • 浏览: 122246 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

open_cursors

阅读更多
open_cursors的讨论

数据库环境9.2.0.4 RAC两个节点
错误现象:
ORA-00604: error occurred at recursive SQL level 1 ORA-01000: maximum open cursors exceeded

问题描述:最近发布了多个大的应用程序后发现open_cursors不够,而且跟recursive SQL有关,我就怀疑可能是跟触发器或者跟什么表的约束有关(注意我们的表空间设置基本都是设置Uniform),后来查看,发现涉及到有个触发器,并且涉及到删除某个有约束的表,但是现在还不能完全确定。
我用select sid,count(*) from v$open_cursor group by sid;

       SID   COUNT(*)
---------- ----------
        16         39
        20         11
        21         55
        26          3
        27         49
        29          5
        30          5
        31         54
        32         22
        33         17
        39         23


SQL>  show parameter open_cursor

NAME                                 VALUE
------------------------------------ ------------------------------
open_cursors                         200

.....
没有发现很大的值
我现在打算用alter system set open_cursors=300 scope=both;暂时增加这个open_cursors。
然后用alter session set events '604 trace name errorstack level 10';
alter session set events '1000 trace name errorstack level 3';
跟踪一下错误,查查究竟是什么原因。如果再发生错误,等会给大家发信息上来。

我们先看看open_cursors的概念:
open_cursors--每个用户同一时刻最多在使用的cursor数

可以有两种级别来调整:
1.Tuning at the DATABASE LEVEL
可能是由于程序过多申请cursor,修改程序,如果实在不够,那么就
alter system set open_cursors=300 scope=both;
增加他。
也有可能是由于大的insert等,而被cancel掉时,或者是一个死连接,查看sqlnet.expire_time
> 0
但是盲目增大他不是一个解决办法,因为不能更好的识别所有的cursor,而且会多使用一些内存,但对性能影响多大,谁有这方面的经验。

2. Tuning at the APPLICATION LEVEL

HOLD_CURSOR是保持静态cursor(program cursor被预编译的),保持这些静态cursor可以减少重解析次数
RELEASE_CURSOR 是一些动态的cursor(oracle cursor) ,用于释放这些资源,也可以减少重解析次数。
是基于cursor cache的使用规则
我们可以通过设置HOLD_CURSOR=NO和RELEASE_CURSOR =YES来调整对open_cursors的要求。

我们来看看tom的实例来了解一下,来了解一下open_cursors 的变化:但我在后面有一些疑惑,大家一起来讨论

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
  2  from v$statname a, v$mystat b
  3  where a.statistic# = b.statistic#
  4  and lower(a.name) like '%' || lower('&1')||'%'
  5  /
old   4: and lower(a.name) like '%' || lower('&1')||'%'
new   4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              26
opened cursors current                  9
session cursor cache hits               0
session cursor cache count             13
cursor authentications                  1


ops$tkyte@ORA920> declare
  2          type rc is ref cursor;
  3
  4          l_cursor rc;
  5  begin
  6          for i in 1 .. 100
  7          loop
  8                  for j in 1 .. 5
  9                  loop
10                          open l_cursor for 'select * from dual xx' || i;
11                          close l_cursor;
12                  end loop;
13          end loop;
14  end;
15  /

PL/SQL procedure successfully completed.

ops$tkyte@ORA920>
ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
  2  from v$statname a, v$mystat b
  3  where a.statistic# = b.statistic#
  4  and lower(a.name) like '%' || lower('&1')||'%'
  5  /
old   4: and lower(a.name) like '%' || lower('&1')||'%'
new   4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative             529
opened cursors current                  9
session cursor cache hits             400
session cursor cache count            100
cursor authentications                  1

that shows I've 100 cursors in my "cache" ready to be opened faster then
normal -- but I never exceeded my 50 open cursors at a time threshold.

ops$tkyte@ORA920> create or replace procedure p( p_more in boolean default
false
)
  2  as
  3          l_x   number;
  4  begin
  5          select 1 into l_x from dual;
  6          select 2 into l_x from dual;
  7          select 3 into l_x from dual;
  8          select 4 into l_x from dual;
  9          select 5 into l_x from dual;
10          if ( p_more )
11          then
12                  select 6 into l_x from dual;
13                  select 7 into l_x from dual;
14                  select 8 into l_x from dual;
15                  select 9 into l_x from dual;
16                  select 10 into l_x from dual;
17          end if;
18  end;
19  /

Procedure created.

ops$tkyte@ORA920> connect /
Connected.
ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
  2  from v$statname a, v$mystat b
  3  where a.statistic# = b.statistic#
  4  and lower(a.name) like '%' || lower('&1')||'%'
  5  /
old   4: and lower(a.name) like '%' || lower('&1')||'%'
new   4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative               9
opened cursors current                  1
session cursor cache hits               0
session cursor cache count              7
cursor authentications                  0

ops$tkyte@ORA920> exec p

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
  2  from v$statname a, v$mystat b
  3  where a.statistic# = b.statistic#
  4  and lower(a.name) like '%' || lower('&1')||'%'
  5  /
old   4: and lower(a.name) like '%' || lower('&1')||'%'
new   4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              17
opened cursors current                  6     <<<<==== +5
session cursor cache hits               1
session cursor cache count              7
cursor authentications                  5

ops$tkyte@ORA920> exec p( true )

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
  2  from v$statname a, v$mystat b
  3  where a.statistic# = b.statistic#
  4  and lower(a.name) like '%' || lower('&1')||'%'
  5  /
old   4: and lower(a.name) like '%' || lower('&1')||'%'
new   4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              24
opened cursors current                 11    <<<==== +5 more
session cursor cache hits               2
session cursor cache count              7
cursor authentications                 10

ops$tkyte@ORA920> exec p( true )

PL/SQL procedure successfully completed.

ops$tkyte@ORA920> @mystat cursor
ops$tkyte@ORA920> select a.name, b.value
  2  from v$statname a, v$mystat b
  3  where a.statistic# = b.statistic#
  4  and lower(a.name) like '%' || lower('&1')||'%'
  5  /
old   4: and lower(a.name) like '%' || lower('&1')||'%'
new   4: and lower(a.name) like '%' || lower('cursor')||'%'

NAME                                VALUE
------------------------------ ----------
opened cursors cumulative              26
opened cursors current                 11    <<< === same +5
session cursor cache hits               3
session cursor cache count              7
cursor authentications                 11

我疑惑的是
select sid,count(*) from v$open_cursor group by sid;

       SID   COUNT(*)
---------- ----------
        16         39
        20         11
        21         55
        26          3
        27         49
        29          5
        30          5
        31         54
        32         22
        33         17
        39         23

如何看这个cursor已经到达open_cursors200了,是opened cursors current吗?能通过 v$open_cursors看出什么名堂吗?
书上写的很模糊,open_cursors究竟是基于某个用户的一个session同一时刻的最大cursor数(一个session可能在不同时间分布cursor)还是某个用户同一时刻最大cursor数(可以是多个session),
同一时间段是怎么划分的。
希望大家能够给予指点讨论,并对处理上面错误,提出宝贵意见。

 

 

open_cursors 应该是一个session同时打开的cursor的数量上限,如果是web应用的话,设成500-1000都没问题,我一般都设得比较高,反正不会对性能有什么影响,有问题的话也容易查找cursor泄漏得地方,仅根据上面得错误,并不能断定是recursive sql导致cursor泄漏,我的经验是PLSQL小心一点儿得话一般出现cursor泄漏得可能性比较小,JAVA什么的前台程序非常容易出现cursor泄漏.看一下http://asktom.oracle.com/pls/ask ... :F4950_P8_DISPLAYID,F4950_P8_CRITERIA:3512824755435,
仅供参考。

 

你用这句试试  应该能看出当前有多少cursor是没关闭的
select KGLLKFLG,KGLNAOBJ from X$KGLLK where user_name=???? and KGLLKFLG=8;


X$KGLLK 是 v$open_cursor 的底层表  我看见没有释放的游标和释放了的游标之间的差距就是 KGLLKFLG 的数据显示的不同 没释放的在我的试验中都是为8  
其实不光是 select 语句, insert ,delete,update 等语句在运行的时候这个 KGLLKFLG都为8(但这时间非常的短) 我猜是一个lock的等级吧

 

我们先看看V$OPEN_CURSOR的结构
select * from v$fixed_view_definition where view_name ='GV$OPEN_CURSOR';

VIEW_NAME                      VIEW_DEFINITION
------------------------------ ------------------------------------------------------------------------
GV$OPEN_CURSOR     select inst_id,kgllkuse, kgllksnm, user_name, kglh
                               dpar, kglnahsh, kglnaobj from x$kgllk where kglhdn
                               sp = 0 and kglhdpar != kgllkhdl


SQL> select * from tab where tname = 'fanglf';

no rows selected


SQL> select  
  2   ADDR  ,
KGLLKHDL,
KGLHDPAR,
KGLNAOBJ   from x$kgllk where KGLNAOBJ   like '%from tab where tname%'  3    4    5  ;

ADDR     KGLLKHDL KGLHDPAR KGLNAOBJ
-------- -------- -------- ------------------------------------------------------------
40696E4C B78ED998 B78EDF14 select * from tab where tname = :"SYS_B_0"
40652580 B78EDF14 B78EDF14 select * from tab where tname = :"SYS_B_0"

每个SQL语句都会有一个parent cursor ,他由一个句炳(可以在库缓存中通过hash值和hash链中找到)和一个对象列表组成(保存了所有child cursor 的指针)
child cursor 也是由一个句炳和两种堆对象组成,其中用0和6来区分,0保存了一些版本信息,比如不同schema下的相同的对象名,6保存了执行计划。
我们只要关注child cursor (kglhdpar != kgllkhdl)

我在做查询时
select * from dba_objects where rownum <50000
/

在运行阶段

ADDR       KGLLKFLG KGLLKHDL KGLHDPAR KGLNAOBJ
-------- ---------- -------- -------- ------------------------------------------------------------
40696EEC          8 B7D903B0 B7D9092C select * from dba_objects where rownum <:"SYS_B_0"
40696F94          0 B7D9092C B7D9092C select * from dba_objects where rownum <:"SYS_B_0"

状态确实是8
这个8表示这个SQL语句在运行

这个cursor主要是由于应用程序端(JAVA)造成的,测试结果是
1、对于jdbc来说,每一个从Connection中产生的Statement相当于一个Session,此时会在v$session中产生或者重用一条session记录,v$open_cursor中记录的就是每个session打开的cursor数量,一个对多个父子关系。

2、除非Statement close物理关闭,否则在这个session在v$open_cursor中相关联的记录将一直存在,不会释放。 jakarta dbcp数据库连接池有一个StatementCache功能,它不会物理关闭Statement,所以造成了我们的cursor溢出,看来Oracle的Statement不能再客户端进行Cache,当我的cache size就算为1,运行一段时间cursor也会溢出,我们必须Close Statementsession来确保相应Session中打开的游标关闭。

3、系统参数open_cursor的含义就是这个Session中能够打开游标的最大数,用SQL
表示如下:
select max(cursor_count) from (select count(*) cursor_count
from v$open_cursor where user_name='???' group by sid);
         
         当这条SQL返回结果达到open_cursor参数的取值,jdbc就会抛出
         
         Exception : java.sql.SQLException: ORA-01000: maximum open
cursors exceeded

        同时系统将结束此次会话,释放所有的cursor.

由于本人对JAVA的运行机制不了解,所以对第1点我还不敢确认
对于第2点,从获取的信息上看,好象是oracle的statementcache分为硬(物理)关闭,软关闭。
在起用statementcache下,jdbc走的是软关闭,也就是说,即使你在程序中用了stmt.close,
因为cache的作用,在db端,将仍然当作open着。为了起用软关闭,导致ORA-01000,用户通常需要设置cachesize,
在oracle jdbc中呢,这些实现都比较正常,然而在hiberate中呢,它采用的是一种非正常的方法,在这一方法下,
cachesize就不起作用。或者更准确的话,cachestatement将不起作用

 

 

出现这个问题主要问题在程序部分,打开了ResultSet或Statement,不关闭造成的。

 

SQL> desc v$Open_cursor
名称                                      是否为空? 类型
----------------------------------------- -------- -------------------

SADDR                                              RAW(4)
SID                                                NUMBER
USER_NAME                                          VARCHAR2(30)
ADDRESS                                            RAW(4)
HASH_VALUE                                         NUMBER
SQL_TEXT                                           VARCHAR2(60)
http://download-west.oracle.com/ ... /ch3126.htm#1119187
This view lists cursors that each user session currently has opened and parsed.

我平常都是通过sql_text找到游标泄漏的sql语句。




这个cursor主要是由于应用程序端(JAVA)造成的,测试结果是
1、对于jdbc来说,每一个从Connection中产生的Statement相当于一个Session,此时会在v$session中产生或者重用一条session记录,v$open_cursor中记录的就是每个session打开的cursor数量,一个对多个父子关系。

每个connection是一个siesession,每个statement值相当于打开一个游标,要不然那么多session怎么 trace 啊

还有关于session cache cursor,确实有用,到了10g为什么默认还是0那?

 

 

游标数量的不够用主要跟你的程序有关系,主要是STATEMENT和RESULT没有关闭掉,还有如果你的session_cached_cursors 这个值有很大关系,缺省值为0。ORACLE游标系统自动管理的,肯定是回收的。但是具体的机制只能问ORACLE的人了。

 

 

对于象PLSQL可以实现缓存游标,这样可以设置session_cached_cursors减少软解析的次数,也就是实现softer SOFT parse

我的理解是
硬解析  --就象一个新厨师做一道菜,这个菜的做法可能要根据自己经验怎么调配起来比较可口,所以他可能需要更多的时间去分析调配技巧.
软解析 --就好比这道菜的调配方法,这个厨师已经掌握了,只需要按照原先制定的工序进行,这道菜可能就很快就可以做出来了.
软软解析 --就好比这道菜做了几套(session_cached_cursors=n)用于备用,如果有客人又要点这道菜的话,就直接拿备用的菜给他好了,是不是更快;)(这也够损的,让客人吃冷菜呵呵),不知道理解有没有出入

我们看看官方的描述:
session_cached_cursors
说明: 指定要高速缓存的会话游标的数量。对同一 SQL 语句进行多次语法分析后,
    它的会话游标将被移到该会话的游标高速缓存中。这样可以缩短语法分析的时间,
因为游标被高速缓存, 无需被重新打开。
看看实例:
SQL> alter session set session_cached_cursors=0;
SQL> select * from emp;  -- hard parse
SQL> select * from emp; -- soft parse
SQL> select * from emp; -- soft parse
SQL> alter session set session_cached_cursors=100;
SQL> select * from emp;  -- soft parse
SQL> select * from emp; -- kinder, gentler, soft parse
值范围: 0 到根据操作系统而定的值。
默认值: 0

 

关于JDBC:

当建立一个connection,在oracle中会建立一个session(a new record in V$session); 当生成一个resultSet,oracle中会建立一个cursor(a new record in v$open_cursor)

 

 

分享到:
评论

相关推荐

    oracle参数open_cursors与session_cached_cursors详解.pdf

    oracle参数open_cursors与session_cached_cursors详解.pdf

    Oracle数据库游标连接超出解决方案

    show parameter open_cursors 2.修改游标数 alter system set open_cursors = 10000; 3.获取打开的游标数 select o.sid, osuser, machine, count(*) num_curs from v$open_cursor o, v$session s where user_...

    数据库参数设置技术手册

    4.11 OPEN_CURSORS 6 4.12 SERVICE_NAMES 6 4.13 SHARED_POOL_SIZE 6 4.14 SORT_AREA_SIZE 7 4.15 JAVA_POOL_SIZE 7 4.16 LARGE_POOL_SIZE 7 4.17 HASH_POOL_SIZE 7 4.18 SHARED_POOL_RESERVED_SIZE 7 4.19 SESSION_...

    超出打开游标的最大数的原因和解决方案

    本文对ORA-01000_maximum_open_cursors_exceeded_超出打开游标的最大数的原因和解决方案有详细描述

    有哪些初始化参数最影响Oracle系统性能

    有哪些初始化参数最影响Oracle系统的性能?具体影响Oracle系统性能的初始化参数有:SGA(系统全局区);db_block_buffers;share_pool_size ;...open_cursors等等。 &lt;?xml:namespace prefix = o /&gt; 等等

    ORACLE DBA 手册

    调整Open_cursors 8 调整Data_links 8 调整系统进程数Processes 9 调整会话Sessions 9 调整事务transactions 9 调整Job数量 10 调整读取数据最大块数 10 设置lock_sga: 11 设置timed _ statistics 11 调整最大回退段...

    ORACLE数据库 安装配置规范 (V2.0.1)

    6.2.1.9 OPEN_CURSORS 36 6.2.1.10 MAX_DUMP_FILE_SIZE 36 6.2.1.11 PARALLEL_MAX_SERVER 36 6.2.1.12 PARALLEL_EXECUTION_MESSAGE_SIZE 37 6.2.1.13 FAST_START_MTTR_TARGET 37 6.2.1.14 INSTANCE_GROUPS(RAC) 37...

    oracle实验报告

    *.open_cursors=300 *.processes=150 *.remote_login_passwordfile='EXCLUSIVE' *.undo_tablespace='UNDOTBS1' 4、创建实例与密码文件 oradim -new -sid mydb -startmode manual -intpwd mydb -pfile E:\app...

    oracle DBA日常脚本

    ..........\Open_Cursors.sql ..........\Pipes.sql ..........\RBS_Extents.sql ..........\RBS_Stats.sql ..........\Recovery_Status.sql ..........\Roles.sql ..........\Search_Source.sql .............

    Oracle9i的init.ora参数中文说明

    Oracle9i初始化参数中文说明 Blank_trimming: 说明: 如果值为TRUE, 即使源长度比目标长度 (SQL92 兼容) 更长, 也允许分配数据。 值范围: TRUE | FALSE 默认值: FALSE serializable: 说明: 确定查询是否获取表级...

    ORACLE9i_优化设计与系统调整

    §3.4.22 打开的光标数(OPEN_CURSORS) 77 §3.4.23 优化方式(OPTIMIZER_MODE) 77 §3.4.24 进程数(PROCESSES) 77 §3.4.25 回滚段名称(ROLLBACK_SEGMENTS) 78 §3.4.26 服务名(SERVICE_NAMES) 78 §3.4.27 会话的数...

    Bibata_Cursor:基于材料的游标:rocket:

    Bibata是OpenSource ,紧凑和材料设计的光标集。 该项目掌握了改善Cursor体验的能力。 Bibata Amber:淡黄色主题。 Bibata Classic:纯黑色主题。 Bibata Ice:轻主题。Bibata风格Bibata原文:锋利的Bibata游标...

    SQL Server里面如何检查没有释放的游标

    一直以来对SQL SERVER的游标都不怎么感冒,也很少使用SQL Server里面的游标,前几天有一位网友问如何检查数据库里面没有...其实SQL SERVER提供了一个动态管理函数sys.dm_exec_cursors,它返回有关在各种数据库中打开的

    SQL Server查看未释放游标的方法

    一直以来对SQL SERVER的游标都不怎么感冒,也很少使用SQL Server里面的游标,前几天有一位网友问...其实SQL SERVER提供了一个动态管理函数sys.dm_exec_cursors,它返回有关在各种数据库中打开的游标的信息。 SELECT

    sublime-align-cursors:在一行上对齐多光标

    | Open project folder | f10 [cursor]| OpenPath: Open project folder | | Open file folder | ctrl+f10 [cursor]| OpenPath: Open file folder | # after | Open project folder | f10 [cursor]| OpenPath: Open ...

    Microsoft Visual Studio

    Common\Graphics\bitmaps\tlbr_w95\open.bmp Common\Graphics\bitmaps\tlbr_w95\paste.bmp Common\Graphics\bitmaps\tlbr_w95\print.bmp Common\Graphics\bitmaps\tlbr_w95\prop.bmp Common\Graphics\bitmaps\...

    ora分析脚本

    - sessions: currently open sessions - stack &lt;os_pid&gt; get process stack using oradebug - cursors [all] &lt;match_str&gt;: [all] parsed cursors - sharing &lt;sql_id&gt;: print why cursors are not shared - ...

    BerkeleyDB-Core-c++-GSG

    Database Open Flags ............ 11 Administrative Methods ........... 11 Error Reporting Functions .......... 13 Managing Databases in Environments ...........15 Database Example .......... 17 3. ...

    Embeded Browser 2.0.0

    support for Chromium's open codecs (h.264/mp3 not licensed) - Render SVGs - Customize cursors - Experimental support for Adobe Flash - Page inspector - Edit/delete cookies - Customizable mouse/...

    Android.SQLite.Essentials.1783282959

    SQLite is an open source relational database management system. Android uses the SQLite database to store and retrieve data persistently. The driving force behind the platform is the database, ...

Global site tag (gtag.js) - Google Analytics