• ORA-01000: maximum open cursors exceeded


    本文转自:http://www.linuxidc.com/Linux/2013-06/86057.htm

    关于ora-01000:超出最大可打开的游标数 的一点理解
     ORA-01000: maximum open cursors exceeded"怎么解决
     ERROR at line 1:
     ORA-01000: maximum open cursors exceeded

    问题分析:
     1.游标open后,出错了又没有close.
     2.可能是表结构的问题。
     
    解决方法:
     step 1:
        查看数据库当前的游标数配置
        show parameter open_cursors;
     

    step 2:
        查看游标使用情况:
     select o.sid, oSUSEr, machine, count(*) num_curs
     from v$open_cursor o, v$session s
     where user_name = 'user' and o.sid=s.sid
     group by o.sid, osuser, machine
     order by  num_curs desc;
     
    此处的user_name='user'中,user代表占用数据库资源的数据库用户名.
     

    step 3:
        查看游标执行的sql情况:
     select o.sid q.sql_text
     from v$open_cursor o, v$sql q
     where q.hash_value=o.hash_value and o.sid = 123;
     
    step 4:
        根据游标占用情况分析访问数据库的程序在资源释放上是否正常,如果程序释放资源没有问题,则加大游标数。
        alter system set open_cursors=2000 scope=both;
        
     以上为cursors数确实不够的情况下的处理方法。
     但在有的时候,就算是加大了open_cursor 。譬如,我将游标大小改到了300,还是出现错误,改到1000以后开始出现了ORA-01001:invalid cursors。再怎么加大
     open_cursors的数量都无济于事。碰到这种情况极可能就是表结构的问题了。
     

    那么如何来验证呢?
     案例来自itpub,yangtingkun:
     “我们系统的数据量比较大,近200张表,有些表一天要插入1000000条左右的数据。表是使用ER/STDIO设计的,然后直接生成建表的脚本,由于没有设置physical_attributes_clause语句中的建表参数,因此使用了默认的参数。好像是INITIAL 10K NEXT 10K PCTFREE 20 PCTUSED 50由于表的存储空间太小,在
     很短的时间内就会装满,因此Oracle就需要不停为30多张表(数据量较大的)申请空间。于是在程序运行了一段时间后,开始出现ORA-01000: maximum open 
     cursors exceeded的错误。 我将游标大小改到了300,还是出现错误,改到1000以后开始出现了ORA-01001:invalid cursors。再怎么加大open_cursors的数量都
     无济于事。 使用select * from v$open_cursors查询,发现有几百条的INSERT语句游标没有释放。 
     
    开始怀疑是程序调用的问题,仔细检查程序没有发现问题。但是发现对某张表进行TRUNCATE操作后,对此表进行插入的游标全部释放,于是开始怀疑是表结构本
     身的问题。重新设置了建表参数,将数据量最大的表的INITIAL和NEXT均设置为50M。至今未再出现同样的错误。”
     

    FYI:
     首先通过v$open_cursor中的SQL_TEXT字段可以查出没有释放的SQL是大致是什么语句。
     由于建表参数设置不当,会有很多的INSERT语句无法释放。
     

    SELECT * FROM V$OPEN_CURSOR WHERE SQL_TEXT LIKE 'INSERT%‘
     
    找一找哪些表的INSERT语句没有释放的游标比较多。从ALL_TABLES里查看该表的建表参数是否合适。
     

    yangtingkun的分析:
     “开始时表参数
     PCT FREE 10
     PCT USED 40
     STORAGE(INITIAL 10K
            NEXT 10K
            MINEXTENTS 1
            MAXEXTENTS 121
            PCTINCREASE 0
            )
     9K的空间,以我们的系统几秒钟就塞满了,下一条插入语句来的时候ORACLE要去自动申请空间,该语句所占用的游标暂时无法释放。ORACLE申请的空间马上又被
     塞满,又要去申请新的空间。如果二、三十多张表在几个钟头内都不停要求ORACLE去进行上述的操作,估计会造成大量的游标来不及释放。以上只是我的估计。”

    补充:
     PCT FREE 10 指当一个block还剩10%的时候就不再进行INSERT了,而使用新的block,剩余部分为update预留。PCT USED 40 指一个block删除数据,数据小于此block空间的40%时,该block重新对INSERT可用,在此之前,此block不用于INSERT。
     
    bit的分析:
     “最理想的状况是initial参数就能装下所有表数据
     不过不可能
     pctincrease设置为0比较好
     不为0你仔细分析后会发现对数据库的负作用很大
     可能碎片更多
     再说也没有那么多空间让smon来合并
     合并了也未必能满足pctincrease导致的不一样的extents的大小.........
     
    pctincrease=1
     只是合并相临的被drop或者truncate释放出来的或者本来就空闲的空间块
     所以……
     呵呵
     想想用处有多大,可能有那些弊端吧
     所谓回收……呵呵
     谁都知道这个可以进行所谓的“回收” ” 

    ASK:
     “我按照yangtingkun的提示使用 SELECT * FROM V$OPEN_CURSOR WHERE  SQL_TEXT LIKE 'INSERT%‘  后,有71条,用到十几个表,大多数有10条左右纪 录,不知道是不是这十几个表未释放游标。但是再执行了一下上面的语句,变成 了151条,用到的表也大多变了。怎样才能找出哪些表的storage设置不合理呢。
     另外,数据库正在使用时修改storage参数会否有问题。”
     
    ANS:
     “每次不一样是正常的,你看到的是你查询时刻正在使用或没有释放的游标。
     可以先锁定一张表,比如发现关于a表的插入记录比较多,可以SELECT * FROM 
     V$OPEN_CURSOR WHERE SQL_TEXT LIKE 'INSERT INTO A %';
     一般来说,同一时间同一用户对一张表的插入操作只有一次。如果发现许多,说明这张表可能有问题。根据我的经验”
     

    解决方法:
     drop掉,然后create
     如果你的数据量比较大,不想重新建表的话,可以直接修改next参数。
     
    SQL> alter table a storage (next 5M);
     
    补充:
     ask:怎样判断该将next 设为多大
     ans:
     next设置为多少要根据你数据量的大小而定了。
     我的经验是:如果每天几百万条的数据量,最好不要小于10M。
     

    总结:
     多数 ORA-01000 还是因为程序没有正常关闭cursor造成的
     比如说,Java 里面createStatement 之后没有close Statment

    补充:在java代码中,执行conn.createStatement()和conn.prepareStatement()
     的时候,实际上都是相当与在数据库中打开了一个cursor。尤其是,如果你的 createStatement和prepareStatement是在一个循环里面的话,就会非常容易出现这个问题。因为游标一直在不停的打开,而且没有关闭。

    一般来说,我们在写Java代码的时候,createStatement和 prepareStatement都应该要放在循环外面,而且使用了这些Statment后,及时关闭。最好是在执行了一次executeQuery、executeUpdate等之后,如果不需要使用 结果集(ResultSet)的数据,就马上将Statment关闭,调用close()方法。

  • 相关阅读:
    Linux下的SVN服务器搭建
    [转][osg]关于PagedLOD 加载卸载机制
    [原][osg]osg文件与osgb文件的区别
    [转][cesium]1.添加本地服务器
    [原][osg][osgearth]倾斜摄影2.文件格式分析:OSGB
    [原][数学][C++][osg]空间向量OA到转到空间向量OB、以及四元素Q1转到Q2的函数
    [原][osgEarth]添加自由飞行漫游器
    [c][c++]按位操作
    [转]QT中QString与string的转化,解决中文乱码问题
    [原][osg][osgearth]倾斜摄影1.介绍
  • 原文地址:https://www.cnblogs.com/Jtianlin/p/4284564.html
Copyright © 2020-2023  润新知