Skip to Main Content

Breadcrumb

XMAS_TREE

The AskTOM team is taking a break over the holiday season, so we're not taking questions or responding to comments, but we might still sneak in a few Office Hours sessions! Thanks for being a member of the AskTOM community.

Question and Answer

Tom Kyte

Thanks for the question, Connie.

Asked: November 27, 2000 - 2:42 pm UTC

Last updated: July 01, 2013 - 5:28 pm UTC

Version: 8.1.6

Viewed 50K+ times! This question is

You Asked

Tom,
Could you please explain why I see cursors in the V$OPEN_CURSOR view even though I believe they are closed. Are they really open?I wrote a small example to illustrate my question.

SQL> start cursortest
SQL> select sql_text
2 from v$open_cursor where upper(sql_text) like ('%CURSORTEST%');

no rows selected
SQL> create or replace procedure testit
2 as
3 junk varchar2(1);
4 CURSOR dual_cursor
5 IS
6 SELECT dummy cursortest
7 FROM dual;
8 begin
9 open dual_cursor;
10 fetch dual_cursor into junk;
11 close dual_cursor;
12 end;
13 /
Procedure created.

SQL> --
SQL> begin testit;end;
2 /
PL/SQL procedure successfully completed.
SQL> --
SQL> select sql_text
2 from v$open_cursor where upper(sql_text) like ('%CURSORTEST%');

SQL_TEXT
------------------------------------------------------------
SELECT DUMMY CURSORTEST FROM DUAL

Thanks for any any help you can provide.
Connie Halpin





and Tom said...

See

</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:553222846752 <code>
for the solution. V$OPEN_CURSOR represents a set of cached cursors the server has for you. The query


select a.value, b.name
from v$mystat a, v$statname b
where a.statistic# = b.statistic#
and a.statistic#= 3

gives you the actual number of truely open cursors



Rating

  (45 ratings)

We're not taking comments currently, so please try again later if you want to add a comment.

Comments

The query always return 1 open cursor

A reader, June 25, 2002 - 2:58 pm UTC

Hi Tom,
Two questions:
1. I run you query listed here
select a.value, b.name
from v$mystat a, v$statname b
where a.statistic# = b.statistic#
and a.statistic#= 3;
The result is the same in any databases I have (9 in total) at any time.
VALUE NAME
--------- ------------------------
1 opened cursors current

I think this is not the case.

2. When I run
select count(*) from v$open_cursor;
I get 1996 as the result. However, my parameter file setting is:
Open cursors = 1000.
How can that be? You have explained above that v$open_cursor is not the currently open cursors. Should the number returned from v$open_cursor smaller than the setting in parameter file, 1000 in my case, even though the number is not the actually openning cursors? The database has no problem.
Thank you very much.

Tom Kyte
June 25, 2002 - 4:33 pm UTC

1) and ... why do you believe that?  care to explain why you think it is wrong (i don't think it is wrong)


SQL*Plus: Release 8.1.7.0.0 - Production on Tue Jun 25 15:35:20 2002
(c) Copyright 2000 Oracle Corporation.  All rights reserved.
Connected to:
Oracle8i Enterprise Edition Release 8.1.7.3.0 - Production
With the Partitioning option
JServer Release 8.1.7.3.0 - Production

ops$tkyte@ORA817DEV.US.ORACLE.COM> select a.value, b.name 
  2              from v$mystat a, v$statname b 
  3             where a.statistic# = b.statistic# 
  4               and a.statistic#= 3;

     VALUE NAME
---------- ------------------------------
         1 opened cursors current

2) select sid, count(*) from v$open_cursor group by sid

open_cursor is by session.  You are looking across sessions. 

Clearing up confusion regarding Open Cursors

Mary Ruiz, December 10, 2002 - 10:48 am UTC

I looked all over for this information. I am trying to set up alerting before the ORA-1000 error is posted in the alert log. I am now changing my code to count the maximum number of open cursors for a session, and check it against a threshold value, instead of counting all open cursors for a session

Just to clarify

Robert, March 12, 2003 - 4:58 am UTC

Tom

After testing would I be right in saying then that the query:

SELECT a.VALUE, b.NAME
FROM v$mystat a, v$statname b
WHERE a.statistic# = b.statistic#
AND a.statistic#= 3

Returns only those open cursors for your current session? If this is so, how do you get all the open cursors for the database? Would you use v$open_cursors then?
Thanks
R.

Tom Kyte
March 12, 2003 - 7:59 am UTC

you would use v$sesstat.

I did a bad thing here too -- i should have coded using the NAME not the number:


ops$tkyte@ORA9I> select a.value, b.name
  2    from v$mystat a, v$statname b
  3   where a.statistic# = b.statistic#
  4     and b.name = 'opened cursors current'
  5  /

     VALUE NAME
---------- ------------------------------
         1 opened cursors current

ops$tkyte@ORA9I> select sum(a.value), b.name
  2    from v$sesstat a, v$statname b
  3   where a.statistic# = b.statistic#
  4     and b.name = 'opened cursors current'
  5   group by b.name
  6  /

SUM(A.VALUE) NAME
------------ ------------------------------
          94 opened cursors current

 

Oops i did it again...

Robert, March 12, 2003 - 5:29 am UTC

Sorry about that Tom,
a little more investigation leads me to believe that if you have a 1000 set as max number of open cursors you are allowed a 1000 per session, for all sessions. Is this correct.

Also I replaced v$mystat with v$sesstat to get all the session open cursors. Is this the correct view? If so is it misleading that it gives me the same number of open cursors as v$open_cursors does?

Cheers
R.

Tom Kyte
March 12, 2003 - 8:02 am UTC

You are allowed 1000 PER SESSION. so there could be 10,000 of them if you have 10 sessions.

if you are in a single user database -- v$sesstat and v$mystat will return basically the same thing for opened cursors current unless smon or some other background process is awake and doing something.

v$open_cusor has a higher value than your last query?

Doug, April 08, 2003 - 7:05 pm UTC

Hi Tom - 
I tried this - 

SQL> select sum(a.value), b.name
      from v$sesstat a, v$statname b
     where a.statistic# = b.statistic#
       and b.name = 'opened cursors current'
     group by b.name
  2    3    4    5    6  /

SUM(A.VALUE) NAME
------------ ------------------------------------------------------------
         515 opened cursors current

SQL> select count(1) from v$open_Cursor;

  COUNT(1)
----------
       377

SQL>

How can v$open_cursor contain less than your query? 

Tom Kyte
April 08, 2003 - 7:29 pm UTC

v$open_cursor = your session.

v$sesstat (summed over) = sum of all sessions.

? v$open_cursor has a sid column

Doug, April 08, 2003 - 11:48 pm UTC

How can v$open_cursor be only my own cursors? It has a sid column.

Tom Kyte
April 09, 2003 - 8:11 am UTC

never mind, restart....(geez, i even said myself:

...
2) select sid, count(*) from v$open_cursor group by sid

open_cursor is by session.  You are looking across sessions. 
......

above) thats what I get for firing off an answer too fast.  thanks for checking back.


but anyway, on a busy system -- one would expect there to be differences -- cursors come and cursors go.  All you need is one session to exit between calls and bamm -- there go hundreds of cursors potentially.

Now, since V$ views are *not* read consistent -- they are 100% point in time pictures -- at the point in time you look at them -- you'll see this.  

http://docs.oracle.com/docs/cd/B10501_01/server.920/a96536/ch3.htm#1086021

Even if you try a single query like so:

ops$tkyte@ORA9I> select sum(a.value), b.name
  2  from v$sesstat a, v$statname b
  3  where a.statistic# = b.statistic# and b.name = 'opened cursors current'
  4  group by b.name
  5  union all
  6  select count(*), 'v$open_cursor' from v$open_cursor
  7  /

SUM(A.VALUE) NAME
------------ ------------------------------
         100 opened cursors current
         129 v$open_cursor

ops$tkyte@ORA9I> /

SUM(A.VALUE) NAME
------------ ------------------------------
          85 opened cursors current
         129 v$open_cursor

ops$tkyte@ORA9I> /

SUM(A.VALUE) NAME
------------ ------------------------------
         110 opened cursors current
         175 v$open_cursor

ops$tkyte@ORA9I> /

SUM(A.VALUE) NAME
------------ ------------------------------
          91 opened cursors current
          97 v$open_cursor

ops$tkyte@ORA9I> /

SUM(A.VALUE) NAME
------------ ------------------------------
         144 opened cursors current
         137 v$open_cursor

ops$tkyte@ORA9I> /

SUM(A.VALUE) NAME
------------ ------------------------------
         146 opened cursors current
          95 v$open_cursor


v$sesstat is queried at a different point in time then v$open_cursor.  Both answers are *right* at their respective points in time.  If you do this on a "single user" system -- you'll see much more predicable responses.

 

Great Tom,Explained in an easily perceptible manner, > 5*

Saminathan Seerangan, April 25, 2003 - 1:19 am UTC


Monitoring

Harri, October 22, 2003 - 5:22 pm UTC

Is there a way to monitor open_cursors usage? I want to get noted if open_cursors parameter is too small.

My monitoring "sofware" uses this query:

select value-(select max(value) from v$sesstat where STATISTIC#='3') from v$parameter where name='open_cursors';

...but sometimes, some databases it gives negative value, so my logic must be wrong or there is a bug or something.


Tom Kyte
October 22, 2003 - 6:29 pm UTC

well, statistic# is a number (why are you comparing to a string????)

are you sure that 3 is open cursors in your database (i should not have used 3 myself)



...

Harri, October 23, 2003 - 6:44 am UTC

SQL> select STATISTIC#, name from v$sysstat where NAME='opened cursors current';

STATISTIC# NAME
---------- ----------------------------------------------------------------
         3 opened cursors current

SQL> 


SQL> select value-(select max(value) from v$sesstat where STATISTIC#='3') from 
v$parameter where name='open_cursors';   

VALUE-(SELECTMAX(VALUE)FROMV$SESSTATWHERESTATISTIC#='3')
--------------------------------------------------------
                                                    2677

SQL> show parameter open_cursors

NAME                                 TYPE    VALUE
------------------------------------ ------- ------------------------------
open_cursors                         integer 3000

SQL> select value-(select max(value) from v$sesstat where STATISTIC#=3) from v$parameter where name='open_cursors';

VALUE-(SELECTMAX(VALUE)FROMV$SESSTATWHERESTATISTIC#=3)
------------------------------------------------------
                                                  2677


...but sometimes it gives negative values!?
 

Tom Kyte
October 23, 2003 - 12:48 pm UTC

so, select the max value as well -- see what it "is".

Open Cursors

Dan Clamage, October 23, 2003 - 1:41 pm UTC

Great! Now will this show me ref cursors as well as "regular" cursors? I don't think it does (after running a quick test). So I can find out whether my web app has a ref cursor leak (ref cursors being opened but never closed). We use connection pooling so a session may stay active for quite some time.

Tom Kyte
October 23, 2003 - 1:47 pm UTC

ref cursors ARE regular cursors.

yes, it'll show you.


ops$tkyte@ORA920LAP> select name, value
  2   from v$mystat a, v$statname b
  3   where a.statistic# = b.statistic#
  4    and b.name = 'opened cursors current'
  5  /

NAME                                VALUE
------------------------------ ----------
opened cursors current                  1

ops$tkyte@ORA920LAP>
ops$tkyte@ORA920LAP> variable x refcursor
ops$tkyte@ORA920LAP> variable y refcursor
ops$tkyte@ORA920LAP> variable z refcursor
ops$tkyte@ORA920LAP>
ops$tkyte@ORA920LAP> exec open :x for select * from dual;

PL/SQL procedure successfully completed.

ops$tkyte@ORA920LAP> /

NAME                                VALUE
------------------------------ ----------
opened cursors current                  2

ops$tkyte@ORA920LAP> exec open :y for select * from dual;

PL/SQL procedure successfully completed.

ops$tkyte@ORA920LAP> /

NAME                                VALUE
------------------------------ ----------
opened cursors current                  3

ops$tkyte@ORA920LAP> exec open :z for select * from dual;

PL/SQL procedure successfully completed.

ops$tkyte@ORA920LAP> /

NAME                                VALUE
------------------------------ ----------
opened cursors current                  4

 

ref cursors strike again

Dan Clamage, October 23, 2003 - 2:43 pm UTC

I think I see what's going on here.
<pre>
declare
type typ_ref is ref cursor;
v_ref typ_ref;
v_sum number;
v_name varchar2(100);
begin
select name, value
into v_name, v_sum
from v$mystat a, v$statname b
where a.statistic# = b.statistic#
and b.name = 'opened cursors current';

dbms_output.put_line(v_name || ': ' || v_sum);

open v_ref for select 1 from dual;
open v_ref for select 'test' from dual;
open v_ref for select user from dual;
open v_ref for select sysdate from dual;
open v_ref for select * from dual;

select name, value
into v_name, v_sum
from v$mystat a, v$statname b
where a.statistic# = b.statistic#
and b.name = 'opened cursors current';

dbms_output.put_line(v_name || ': ' || v_sum);
end;
/

opened cursors current: 7
opened cursors current: 9
</pre>

My cursor space is being reused. I was expecting Oracle to store all the different queries in memory.

Thanks!

...

Harri, October 24, 2003 - 3:51 am UTC

SQL> select STATISTIC#, name from v$sysstat where NAME='opened cursors current';

STATISTIC# NAME
---------- ----------------------------------------------------------------
         3 opened cursors current


SQL> select max(VALUE) from v$sesstat where STATISTIC#=3;
MAX(VALUE)
----------
381

SQL> show parameter open_cursors
NAME TYPE VALUE
------------------------------------ ------- ------------------------------
open_cursors integer 150

SQL> select value-(select max(value) from v$sesstat where STATISTIC#='3')
2 from v$parameter where name='open_cursors';
VALUE-(SELECTMAX(VALUE)FROMV$SESSTATWHERESTATISTIC#='3')
--------------------------------------------------------
-231
 

Tom Kyte
October 24, 2003 - 9:37 am UTC

any chance someone did an alter system?


ops$tkyte@ORA920> select STATISTIC#, name from v$sysstat where NAME='opened cursors current';
 
STATISTIC# NAME
---------- ------------------------------
         3 opened cursors current
 
ops$tkyte@ORA920>
ops$tkyte@ORA920> select max(VALUE) from v$sesstat where STATISTIC#=3;
 
MAX(VALUE)
----------
        10
 
ops$tkyte@ORA920>
ops$tkyte@ORA920> show parameter open_cursors
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
open_cursors                         integer     500
ops$tkyte@ORA920>
ops$tkyte@ORA920> select value-(select max(value) from v$sesstat where STATISTIC#='3')
  2    from v$parameter where name='open_cursors';
 
VALUE-(SELECTMAX(VALUE)FROMV$SESSTATWHERESTATISTIC#='3')
--------------------------------------------------------
                                                     490
 
ops$tkyte@ORA920>
ops$tkyte@ORA920> alter system set open_cursors = 5;
 
System altered.
 
ops$tkyte@ORA920>
ops$tkyte@ORA920> show parameter open_cursors
 
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
open_cursors                         integer     5
ops$tkyte@ORA920>
ops$tkyte@ORA920> select value-(select max(value) from v$sesstat where STATISTIC#='3')
  2    from v$parameter where name='open_cursors';
 
VALUE-(SELECTMAX(VALUE)FROMV$SESSTATWHERESTATISTIC#='3')
--------------------------------------------------------
                                                      -5
 
ops$tkyte@ORA920>
 

open_cursors

Sikandar Hayat, April 01, 2004 - 12:27 am UTC

I have Oracle 9i R2 application and 9i R2 database server. The open_curosrs were default on db server. The application server stopped responding so it was suggested by the application developer that open_cursors should be increased. Now let me know,

1- Is there any calculations method for open_cursors?
2- If application is not using bind variables so is this the reason that we have to increase open_cursors?
3- If the open_cursors are increased then what will be the performance impact on the db server and the memory usage?

Thanks for your time.

Tom Kyte
April 01, 2004 - 10:01 am UTC

why would you increase open_cursors?

why wouldn't you figure out "what happened"?

Unless you are getting ora-1000 max open cursors exceeded, upping it won't fix anything.

1) you need to set it high enough to not get ora-1000, it is dependent on the applications needs

2) no, you have a bug in the code that the java developers MUST fix though.

3) if you are not hitting ora-1000, it will change nothing (since you are not using the cursors you currently have)


why an app server "not responding" would give a gut reaction of "up open cursors" is beyond me though..

Nice info.

Sikandar Hayat, April 01, 2004 - 10:37 am UTC

Ya you are right that it should be only increased when the error hits. I would like to know that what kind of bug do you think may be in the application,

2) no, you have a bug in the code that the java developers MUST fix though.

No use of baind variables may be one of the reasons?



Tom Kyte
April 01, 2004 - 10:53 am UTC

there are an infinite number of possible bugs.



not using bind variables in a transactional application is definitely a bug.

prat, July 21, 2004 - 6:54 pm UTC

Hi Tom, 

I have the following PL/SQL block: 

SQL> declare
  2    procedure x is
  3      cursor c is select ename from emp;
  4      v_ename emp.ename%TYPE;
  5    begin
  6      open c;
  7      fetch c into v_ename;
  8      dbms_output.put_Line(v_ename);
  9      -- Let's not bother to close c
 10    end;
 11  begin
 12    for i in 1..5 loop
 13      x;
 14    end loop;
 15* end;
SQL> /
SMITH
SMITH
SMITH
SMITH
SMITH

I would like to know, if it would hog the memory (especially if I increase the counter) ? It does not show these as open cursors though !

Can you please throw some light on this ..

Thanks 

Tom Kyte
July 21, 2004 - 7:11 pm UTC

that is an infinite loop that fails only because dbms_output fails it.

the cursor is closed for you as it goes out of scope. only if its scope what "global" (defined in a package spec or body outside of a function) would it remain "in scope" and be a potential problem.

Open Cursors ?

prat, July 21, 2004 - 8:54 pm UTC

SQL> set serveroutput on size 1000000
SQL> variable myref refcursor
SQL> DECLARE
  2  TYPE emp_cur_t is REF CURSOR return SCOTT.EMP%ROWTYPE;
  3  v_cur      emp_cur_t;
  4  emp_rec     scott.emp%rowtype;
  5  procedure x is
  6  begin
  7  open v_cur for select * from scott.emp where rownum <= 10;
  8  fetch v_cur into emp_rec;
  9  DBMS_OUTPUT.PUT_LINE(emp_rec.ename);
 10  :myref := v_cur;
 11  end;
 12  begin
 13  for i in 1..5 loop
 14  x;
 15  end loop;
 16  end;
 17  /
SMITH
SMITH
SMITH
SMITH
SMITH

PL/SQL procedure successfully completed.

SQL> print myref

     EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM
---------- ---------- --------- ---------- --------- ---------- ----------
    DEPTNO
----------
      7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300
        30

      7521 WARD       SALESMAN        7698 22-FEB-81       1250        500
        30

      7566 JONES      MANAGER         7839 02-APR-81       2975
        20

      7654 MARTIN     SALESMAN        7698 28-SEP-81       1250       1400
        30

      7698 BLAKE      MANAGER         7839 01-MAY-81       2850
        30

      7782 CLARK      MANAGER         7839 09-JUN-81       2450
        10

      7788 SCOTT      ANALYST         7566 19-APR-87       3000
        20

      7839 KING       PRESIDENT            17-NOV-81       5000
        10

      7844 TURNER     SALESMAN        7698 08-SEP-81       1500          0
        30


9 rows selected.

SQL> 

What does this prove to you ? Was the cursor closed after the RETURN happened ? :)) Even if the cursor variable was available at the SQL*Plus prompt, the cursor should have been closed (as per your theory). So, when you print the value of cursor variable, you should'nt get anything (infact you should get an error, because the handle of cursor that was set in the cursor variable, has been closed. Refer the code below, where we would get the error, if we close the cursor explicitly)

Now, let us close the cursor explicitly :

SQL> set serveroutput on size 1000000
SQL> variable myref refcursor
SQL> DECLARE
  2  TYPE emp_cur_t is REF CURSOR return SCOTT.EMP%ROWTYPE;
  3  v_cur      emp_cur_t;
  4  emp_rec     scott.emp%rowtype;
  5  procedure x is
  6  begin
  7  open v_cur for select * from scott.emp where rownum <= 10;
  8  fetch v_cur into emp_rec;
  9  DBMS_OUTPUT.PUT_LINE(emp_rec.ename);
 10  :myref := v_cur;
 11  close v_cur; -- CLOSED EXPLICITLY
 12  end;
 13  begin
 14  for i in 1..5 loop
 15  x;
 16  end loop;
 17  end;
 18  /
SMITH
SMITH
SMITH
SMITH
SMITH

PL/SQL procedure successfully completed.

SQL> print myref
ERROR:
ORA-24338: statement handle not executed


SP2-0625: Error printing variable "myref"
SQL> 

 

Tom Kyte
July 21, 2004 - 9:11 pm UTC

no theory -- the ref cursor is "global in nature" (it was not declared in the local scope of the plsql block) and sqlplus closed it after it exhausted it.

I don't know what you are trying to prove/show?

you compared a locally scoped cursor (example above with "cursor c") to a ref cursor that had a scope controlled by sqlplus itself?????

what you showed is totally expected and doesn't contradict anything I said?

cursor not closed

prat, July 22, 2004 - 4:50 am UTC

Hi Tom,

Sorry for not being explicit.

I was trying to mention that if we do a close within the procedure (where we open the cursor), the cursor actually is closed. But, If we don't put a close in the procedure, the cursor is not closed (even though the procedure has finished).
Cursor is actually defined and opened in the procedure, so when the procedure returns the control to the PL/SQL block, and then to SQL*Plus, you would expect the cursor to be closed. But that does'nt happen.
Also, if you could please let me know why do I get the other 9 records from the table, when I just do one fetch (5 times) ?

Tom Kyte
July 22, 2004 - 7:22 am UTC

that is a REF CURSOR only.  

in your first example "C", a local cursor to that anonymous block is *closed*

in your second example, :myref, a cursor handle owned by sqlplus, is closed only when

a) you close it in plsql before giving it back to sqlplus
b) sqlplus hits "end of fetch" and closes it.

cursor is NOT defined in plsql in your second example:

SQL> variable myref refcursor

it was clearly defined in SQLPlus -- sqlplus owned that cursor.  You would not expect the cursor to be closed -- else there would be NO WAY to return a result set from a stored procedure.

I don't know what you mean by that last paragraph at all???  You fetched a row in plsql -- sqlplus fetched the rest?   

open cursors ... contd. ...

prat, July 22, 2004 - 4:56 am UTC

And ... in the second PL/SQL, you can see that if I do the print (cursor variable), I cannot print it. Which proves that the cursor is not opened. Whereas in case of first PL/SQL, it prints the other records from the cursor, even after the PL/SQL block has executed. I would assume, that since the PLSQL has finished, the cursor should not be open/available for print. I can be sure that it is showing records from the cursor, because it shows only the 10 records that I selected while defining the cursor.

I am just trying to understand what is happening here. Please excuse my inexperience :)

Tom Kyte
July 22, 2004 - 7:27 am UTC

it is not opened because YOU CLOSED IT!!!!

I'm really not understanding where you are going with this.

you assigned the cursor (a single thing) to a global variable :myref. If you left the cursor open, sqlplus gets it and prints it. If you close the cursor, sqlplus doesn't get it, cannot print it.

If you've ever programmed in C, this is alot like:


void x( FILE * * foo )
{
FILE * input;

input = fopen( ..... );
*foo = input;


both input and foo "point" to the same "result set" -- file. close foo -- input is closed. close input, foo is closed.

foo is a ref cursor, a pointer to a result set. if we leave procedure X, the caller can use foo to read/write the "result set". If we closed input before leaving x -- foo would not be usable.

Don't understand

reader, July 22, 2004 - 5:06 am UTC

I am a bit confused here. What has happend when we assign a local declared ref cursor to a global cursor i,e
:myref := v_cur;

If they both represent different cursor then surely closing the local cursor v_cur should not have any impact on the global one. Hence we should be able to print the values from the global cursor at the SQL prompt.

Have I got something wrong here ?

Tom Kyte
July 22, 2004 - 7:28 am UTC

a ref cursor is a pointer to a cursor. they point to the same thing. it did not "copy" the result set.

V$open_cursor and V$sesstat and v$statname give different results

Paru, July 27, 2004 - 12:58 pm UTC

Hi Tom,

Here is the query that I ran on my database as the developer complained about getting ORA-1000, but he is fixing his code and closing the cursors.

But, the results of the queries are so different, can you explain why...

select sum(a.value), b.name
from v$sesstat a, v$statname b
where a.statistic# = b.statistic# and b.name = 'opened cursors current'
group by b.name
union all
select count(*), 'v$open_cursor' from v$open_cursor
;
SUM(A.VALUE) NAME
------------ ----------------------------------------------- 5081 opened cursors current
53 v$open_cursor

OPEN_CURSOR is set at 700.

Tom Kyte
July 27, 2004 - 1:06 pm UTC

hit / a couple of times, does it stay the same?

look by session -- join sesstat to open_cursor to v$session and see which processes have the "big diffs", that might be telling.

A reader, August 17, 2004 - 9:33 pm UTC

Tom,

How can i know how much memory is used by each cursor.

Thanks.

Tom Kyte
August 18, 2004 - 7:44 am UTC

v$sql can show you the shared resource -- the "parsed query itself".

v$sql_cursor has the memory associated with an instance of a cursor (session viewable only)

Is this really true for Open Cursors

Bablu, June 24, 2005 - 10:22 am UTC

We have a typical situation here, wherein the application is throwing TOO MANY CURSORS. We know that we have to fix the application, but in the interim we would like to increase the cursors open to 2000. But, this is the feedback we got :

"Each open cursor consume 2 to 5 MB of memory, depend upon execution work. Setting 2000 cursor means we are reserving memory of 4000MB. You system may crash at some point. We can set the limit to 2000, provided the server can handle this much of memory."

I know this is not true, but how to really determine how much each cursors is taking space in memory.

Tom Kyte
June 24, 2005 - 6:27 pm UTC

each open cursor does not take that amount.

but i would not fix a leaking cursor problem with this -- you have a serious bug in your code, this just moves the wall back a couple of inches You haven't fixed anything.

(this is not a typial situation, this is a bug in the developed code)

ORA-01000 : maximum open cursors exceeded

swain, September 06, 2005 - 12:40 am UTC

Hi Tom,
Could you please explain why I see cursors in the V$OPEN_CURSOR view and in v$sesstat even though they have been explicitly closed in the code.
With each call to this function the number of open cursors increased and leads to ORA-01000 error.
Here is the part of the code used for cursor handling.

EXEC SQL PREPARE S FROM :gSQLStatement;
EXEC SQL DECLARE C CURSOR FOR S;
EXEC SQL OPEN C;
.
.
.
EXEC SQL DESCRIBE SELECT LIST FOR S INTO selda;
.
.
.
EXEC SQL FOR :array_size FETCH C USING DESCRIPTOR selda;
.
.
.
sqlclu(selda);
EXEC SQL CLOSE C;
Thanks,
Swain


Tom Kyte
September 06, 2005 - 8:11 am UTC

can you please put things in one place?

see the other place you put this for comments.

Back to the Original Question by Connie Halpin

Roger, September 23, 2005 - 3:29 pm UTC

Hi, Tom,

I found that your query:

select a.value, b.name
from v$mystat a, v$statname b
where a.statistic# = b.statistic#
and b.name = 'opened cursors current'

still returns a result that includes 'cached cursors' that has been closed.

Here are my test procs and results - should be general enough for any other oracle dbs:

SQL> CREATE OR REPLACE    PROCEDURE OPENCursorTest1
  2      IS
  3  
  4       CURSOR Test_cur
  5       IS
  6    SELECT * FROM global_name
  7    ;
  8  
  9   V_NUM_OPENCURSOR NUMBER;
 10  
 11      BEGIN
 12  
 13   OPEN Test_cur;
 14   CLOSE Test_cur;
 15  
 16   IF Test_cur%ISOPEN THEN
 17  
 18           select a.value INTO V_NUM_OPENCURSOR
 19           from v$mystat a, v$statname b
 20    where a.statistic# = b.statistic#
 21                and b.name = 'opened cursors current';
 22  
 23          DBMS_OUTPUT.PUT_LINE('Test_cur IS OPEN AND NUM OPEN CURSORS ='||TO_CHAR(V_NUM_OPENCURSO
R));
 24    CLOSE Test_cur;
 25          ELSE
 26  
 27           select a.value INTO V_NUM_OPENCURSOR
 28               from v$mystat a, v$statname b
 29              where a.statistic# = b.statistic#
 30                and b.name = 'opened cursors current';
 31          DBMS_OUTPUT.PUT_LINE('Test_cur IS CLOSED AND NUM OPEN CURSORS 
 32  ='||TO_CHAR(V_NUM_OPENCURSOR));
 33  
 34   END IF;
 35  
 36  
 37      END OPENCursorTest1;
 38  /

Procedure created.

SQL> 
SQL> show error;
No errors.

SQL> 
SQL> exec OPENCursorTest1
Test_cur IS CLOSED AND NUM OPEN CURSORS
=3

PL/SQL procedure successfully completed.

SQL> 
SQL> CREATE OR REPLACE    PROCEDURE OPENCursorTest2
  2      IS
  3  
  4       CURSOR Test_cur
  5       IS
  6    SELECT * FROM global_name
  7    ;
  8  
  9   V_NUM_OPENCURSOR NUMBER;
 10  
 11      BEGIN
 12  
 13   OPEN Test_cur;
 14   --CLOSE Test_cur;
 15  
 16   IF Test_cur%ISOPEN THEN
 17  
 18           select a.value INTO V_NUM_OPENCURSOR
 19           from v$mystat a, v$statname b
 20    where a.statistic# = b.statistic#
 21                and b.name = 'opened cursors current';
 22  
 23          DBMS_OUTPUT.PUT_LINE('Test_cur IS OPEN AND NUM OPEN CURSORS ='||TO_CHAR(V_NUM_OPENCURSO
R));
 24    CLOSE Test_cur;
 25          ELSE
 26  
 27           select a.value INTO V_NUM_OPENCURSOR
 28               from v$mystat a, v$statname b
 29              where a.statistic# = b.statistic#
 30                and b.name = 'opened cursors current';
 31          DBMS_OUTPUT.PUT_LINE('Test_cur IS CLOSED AND NUM OPEN CURSORS 
 32  ='||TO_CHAR(V_NUM_OPENCURSOR));
 33  
 34   END IF;
 35  
 36  
 37      END OPENCursorTest2;
 38  /

Procedure created.

SQL> 
SQL> show error;
No errors.

SQL> 
SQL> exec OPENCursorTest2
Test_cur IS OPEN AND NUM OPEN CURSORS =3

PL/SQL procedure successfully completed.

SQL> 

The SQL_TEXTs for the two of the three open cursors are the same for the two cases:
SID    SQL_TEXT

51    SELECT A.VALUE FROM V$MYSTAT A, V$STATNAME B WHERE A.STATIST
51    SELECT * FROM GLOBAL_NAME 

The question is now back to Connie's:
How do we know the "real" open cursors that developers forget to explicitly close in the app codes?

Thanks Tom!

Roger
 

Open Cursors discussion is very helpful

jim basler, September 27, 2005 - 9:22 am UTC

Thanks for having this out here

Maximum No Of Cursor

Mita, March 17, 2006 - 2:51 pm UTC

my process does not have any Open Cursor or Open REF Cursor. there is a call to DBMS_XML.get_xml and it returns out put of it in CLOB to Java program. when I am load testing the app for 300 simultaneous users, I get ora-01000 error. Database version is 10gR1 and parameter is set to 300.

since we are not opening any cursors explictly, why would we get this error ??


Tom Kyte
March 17, 2006 - 5:57 pm UTC

post the smallest test case humanly possible against the scott.emp table.

(what is dbms_xml? for example...)

Also, the java code is managing THEIR cursors (the only way to talk to oracle) correctly right??

Obtaining the text of open cursors

Steve Baldwin, March 22, 2006 - 6:58 pm UTC

I have a situation where I believe my app is leaking cursors, but it would help me a lot to see the SQL text of only the open (as reported by the session_open_cursors function) cursors.

Is this possible?

Thanks.

Tom Kyte
March 22, 2006 - 7:17 pm UTC

what function is that?

Oops

Steve Baldwin, March 22, 2006 - 9:06 pm UTC

Sorry, I just realised that is a function we wrote. It just returns the value for the statistic 'opened cursors current'.

Tom Kyte
March 23, 2006 - 10:11 am UTC

v$open_cursor has the leading bit of sql text and it can be joined to v$sql.

What about the text for *open* cursors

Steve Baldwin, March 23, 2006 - 2:26 pm UTC

As you say above ...

"V$OPEN_CURSOR represents a set of cached cursors the server
has for you. The query [snip] gives you the actual number of truely open cursors."

What I am trying to get is the text for truly open cursors.

Tom Kyte
March 23, 2006 - 2:34 pm UTC

doesn't exist as far as I know.

SQL query for Open Cursors

Archana, March 23, 2006 - 11:08 pm UTC

I am facing a problem in our production. There are some cursors which are not getting closed.

Using following query I am able to get the count of open cursors:

SELECT a.SID, a.VALUE, b.NAME
FROM v$sesstat a, v$statname b, v$session s
WHERE a.statistic# = b.statistic#
AND a.statistic# = 3
AND a.SID = s.SID
AND a.VALUE <> 0;

But I am not able to get the sql queries of those open cursors anyhow.

Can you please help me?

Thanks in Advance.

Tom Kyte
March 24, 2006 - 8:29 am UTC

v$open_cursor

Session_cached_cursor

Anil, March 24, 2006 - 3:28 am UTC

Hi Tom

How does open_cursor and session_cached_cursor relted to. What is the difference between these two.

In the top of this article you had mentioned
<<V$OPEN_CURSOR represents a set of cached cursors the server
has for you. >>

so what is session_cached_cursor will do. a bit confused..

Thanks & Rgds
Anil

Query

Shwetha, April 25, 2006 - 2:35 am UTC

Could you please let me know how to forcibly close the open cursors that are listed in the table V$OPEN_CURSOR

Tom Kyte
April 25, 2006 - 5:37 am UTC

You cannot, the application that owns them is the only thing that can.

And the only things that "cares" really - each session has it's own set of cursors and it's own limit on cursors - It is not like one application can be hogging all of the cursors for the system.

Differences on V$SQL_PLAN

JAIME, July 01, 2009 - 7:22 pm UTC

Hi tom,

Could you please explain the reuslts.
First example Database 9.2.0.8 ( session_cached_cursors=0)
Second example 10.2.0.3 session_cached_cursors=20
Third example 10.2.0.3 session_cached_cursors=0

All examples i just connected to the database:

1)
JServer Release 9.2.0.8.0 - Production

select * from V$MYSTAT where rownum < 2;

SID STATISTIC# VALUE
---------- ---------- ----------
2617 0 1

Transcurrido: 00:00:00.00
variable x refcursor
exec open :x for select * from dual;

Procedimiento PL/SQL terminado correctamente.

Transcurrido: 00:00:00.00
select name, value
from v$mystat a, v$statname b 2
where a.statistic# = b.statistic#
and b.name = 3 4 'opened cursors current';

NAME VALUE
---------------------------------------------------------------- ----------
opened cursors current 4

Transcurrido: 00:00:00.01
select sql_text from V$OPEN_CURSOR where sid=2617;

SQL_TEXT
------------------------------------------------------------
select sql_text from V$OPEN_CURSOR where sid=2617
SELECT * FROM DUAL

Transcurrido: 00:00:00.05
select name, value
from v$mystat a, v$statname b 2
where a.statistic# = b.statistic#
and b.name = 3 4 'opened cursors current';

NAME VALUE
---------------------------------------------------------------- ----------
opened cursors current 4

Transcurrido: 00:00:00.00

EXAMPLE 2)
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

select * from V$MYSTAT where rownum < 2;

SID STATISTIC# VALUE
---------- ---------- ----------
1019 0 1

variable x refcursor
exec open :x for select * from dual;

Procedimiento PL/SQL terminado correctamente.

select name, value
from v$mystat a, v$statname b 2
where a.statistic# = b.statistic#
and b.name = 3 4 'opened cursors current';

NAME VALUE
---------------------------------------------------------------- ----------
opened cursors current 2

select sql_text from V$OPEN_CURSOR where sid=1019;

SQL_TEXT
------------------------------------------------------------
select f.file#, f.block#, f.ts#, f.length from fet$ f, ts$ t
SELECT DECODE('A','A','1','2') FROM DUAL
SELECT USER FROM DUAL
BEGIN open :x for select * from dual; END;
SELECT * FROM DUAL
select * from V$MYSTAT where rownum < 2
select name, value from v$mystat a, v$statname b where a.sta
BEGIN DBMS_APPLICATION_INFO.SET_MODULE(:1,NULL); END;
SELECT CHAR_VALUE FROM SYSTEM.PRODUCT_PRIVS WHERE (UPPER('
DECLARE v_ID NUMBER; v_user VARCHAR2(15); v_program
SELECT ATTRIBUTE,SCOPE,NUMERIC_VALUE,CHAR_VALUE,DATE_VALUE F
select sql_text from V$OPEN_CURSOR where sid=1019

12 filas seleccionadas.

select name, value
from v$mystat a, v$statname b 2
where a.statistic# = b.statistic#
and b.name = 3 4 'opened cursors current';

NAME VALUE
---------------------------------------------------------------- ----------
opened cursors current 2

Third example:

Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, OLAP and Data Mining options

alter session set session_cached_cursors=0;

Sesión modificada.

select * from V$MYSTAT where rownum < 2;

SID STATISTIC# VALUE
---------- ---------- ----------
975 0 1

variable x refcursor
exec open :x for select * from dual;

Procedimiento PL/SQL terminado correctamente.

select name, value
from v$mystat a, v$statname b 2
where a.statistic# = b.statistic#
and b.name = 3 4 'opened cursors current';

NAME VALUE
---------------------------------------------------------------- ----------
opened cursors current 2

select sql_text from V$OPEN_CURSOR where sid=975;

SQL_TEXT
------------------------------------------------------------
update sys.col_usage$ set equality_preds = equality_pre
SELECT * FROM DUAL
select sql_text from V$OPEN_CURSOR where sid=975

select name, value
from v$mystat a, v$statname b 2
where a.statistic# = b.statistic#
and b.name = 3 4 'opened cursors current';

NAME VALUE
---------------------------------------------------------------- ----------
opened cursors current 2


My questions are :

1) Does oracle treat in a different way opened cursors on different versions ¿?
2) Why does oracle detect 4 opened cursors on oracle 9 ¿?
It makes more sense to me the behaviour of oracle 10.


A reader, May 06, 2010 - 2:55 pm UTC

Sir,

I am trying to understand about the 'open_cursors' and 'session_cached_cursors' and to understand them clearly - I want to understand the cursors how they are managed by the client,pl/sql in the above example ..

I have a 3GL application which calls a pl/sql procedure

Any 3GL application
============================
declare a cursor C- CLIENT CURSOR
main()
C=call_plsql_procedure();
end;
==========================

see below the pl/sql procedure

create or replace call_plsql_procedure
as
declare a ref_cursor R - EXPLICIT cursor - 1
curor d is select emp_no from emp; -EXPLICIT CURSOR -2 (Pl/sql)
begin
open d;
fetch d into x
close c ;
update emp set emp_no=emp_no+20 -- IMPLICIT 1
select x from y into z --IMPLICIT 2

end;


Here
Client Cursor - 1
Pl/sql Explicit cursors -2
Pl/sql Implicit cursors - 3

Could you please explain the sequence of the cursors caching/closing above by pl/sql and the client ?

Thanks for your time




Tom Kyte
May 06, 2010 - 8:54 pm UTC

implicit and explicit cursors are both cached by plsql the same - so, we don't need to consider them "differently" - they are to plsql "the same thing"

(ref cursors - they are different however, they are not cacheable)

Here the client has 1 cursor and plsql opens two more.

Plsql will cache OPEN (ignore your close) as many cursors as it can, up to session_cached_cursors (which is less than or equal to open-cursors). So, in this case, probably (assuming session cached cursors > 2), plsql would have 2 cursors open at the end.

The client - the client decides whether to cache or not. The programmer might cache the cursor, the API the programmer uses might. This caching is typically NOT affected at all by session-cached-cursors (it could be, typically is not, you'd have to read the documentation for your client api to see what it does).

The plsql cursor cache is nice because if you have say

open_cursors = 100
session_cached_cursors = 50

and your client has 50 open cursors - and plsql has 50 CACHED OPENED cursors and your client wants to open the 51st cursor - instead of getting an error, plsql will gracefully close a cursor - taking its cache down to 49, giving you the extra cursor handle to open in the client.

A reader, May 09, 2010 - 6:50 am UTC

Hard Parse :
cursor creation,allocate some memory in uga/pga to store the information about SQL,variables etc ,syntax,semantic check,bindng,create a LINK to SGA ,Optimizer will develop the best execution plan and store in SGA .
Soft Parse:
again we do -cursor creation,allocate some memory in uga/pga to store the information about SQL,variables etc ,syntax,semantic check,bindng,HERE WE FIND SAME SQL in SGA and so NO NEED to create an execution plan - again we have to create a link to that SQL ... so everything is same as hard parse excpet that 'execution plan' is not again built in this case.

Softer Soft parse :(curose caching by pl/sql or any 3gl)
nothing we do here ...becuase memory already exists,link to SGA exists , exection plan is there ... just 'execute' it

Is my understaning correct Tom ? Thank you
Tom Kyte
May 10, 2010 - 6:35 pm UTC

softer soft parse is achieved using session_cached_cursors - there the application actually does close the cursor and we have to reopen it - but - if they close it say three times, we finally catch on and say "oh, you didn't really mean to close that" and when we close it - we keep a pointer to it in the shared pool so that when you say open the next time, we check the shared pool (skipping many of the steps like syntax parse, semantic check) to see if it is still there and if so, just execute it.


then there is NO PARSE - that is what plsql code - that is plsql cursor caching.

So, there is:

a) hard parse (very very very bad)
b) soft parse (very very bad)
c) softer soft parse (very bad)
d) NO PARSE (very very very good!)

A reader, May 11, 2010 - 5:39 am UTC

Sir,
Let us say - it is 'dedicated connection'
When the client(3gl) submits a SQL statement for first time - It first creates a pointer an handle -(cursor) on its side ,associates the SQL with it - allocates 'sql area' to hold the information about that sql in pga/uga and make a parse call to server - the client is done now ...

Server parses it , get the execution plan and store them in SGA , now there is a pointer to the SQL in the SGA . so there are 'two' pointers now - one is from client to PGA/uga and second is from PGA/UGA to SGA


Lets say the statement is executed 3 times (open, close, open-close,open -close) - then Server may decide to 'cache' it - in this case -

1.Server 'caches' the cursor - means what happens internally? I mean - here the cursor is closed but the pointer from pga/uga still points to the SQL in SGA though the cursor is closed ....Correct ? but the SQL can be aged out from shared pool as per LRU logic.

2.Will the Client (3gl) also 'cache' cursor as Server does above - (or) does it depend on client side programming ? How it actually 'caches' internally ?

3.Lets say in the above case - the SQL statement is from pl/sql block -
Pl/SQl 'caches' the cursor though the cursor is closed - means what happens ? Here the cursor is still 'open' so everything remains same as if it is open - correct ?
Here the SQL can NOT be aged out from shared pool as the cursor is still open.

A reader, May 24, 2010 - 1:49 pm UTC

Sir,
Let us say - it is 'dedicated connection'
When the client(3gl) submits a SQL statement for first time - It first creates a pointer an
handle -(cursor) on its side ,associates the SQL with it - allocates 'sql area' to hold the
information about that sql in pga/uga and make a parse call to server - the client is done now ...

Server parses it , get the execution plan and store them in SGA , now there is a pointer to the SQL
in the SGA . so there are 'two' pointers now - one is from client to PGA/uga and second is from
PGA/UGA to SGA


Lets say the statement is executed 3 times (open, close, open-close,open -close) - then Server may
decide to 'cache' it - in this case -

1.Server 'caches' the cursor - means what happens internally? I mean - here the cursor is closed
but the pointer from pga/uga still points to the SQL in SGA though the cursor is closed
....Correct ? but the SQL can be aged out from shared pool as per LRU logic.

2.Will the Client (3gl) also 'cache' cursor as Server does above - (or) does it depend on client
side programming ? How it actually 'caches' internally ?

3.Lets say in the above case - the SQL statement is from pl/sql block -
Pl/SQl 'caches' the cursor though the cursor is closed - means what happens ? Here the cursor is
still 'open' so everything remains same as if it is open - correct ?
Here the SQL can NOT be aged out from shared pool as the cursor is still open.

Tom Kyte
May 24, 2010 - 2:32 pm UTC

are you talking about session cached cursors? I think so, because of the magic "3" reference.

conceptually:

The client would call "close", the server process working on behalf of the client would say "oh, you closed it N times already - you are going to open it again, I'll save you some work" and it keeps a pointer to the SGA where this statement is in the shared pool. If you say "open" again - it will peek at that point, look in the shared pool and see if that statement is still there - if so, it can just re-establish everything it needs and execute that cursor.

I (tom) call this a softer soft parse.

Normally:

soft parse:
o parse sql text for syntax, build parse tree
o do a semantic lookup to resolve all items in sql statement - so we know what "T" is in "select * from t" for example
o hash original sql statement to a sql_id
o look up in shared pool for matches
o search the matches for one that matches everything exactly (same tables being queried, same optimizer environment, etc)
o then execute


hard parse:
o everything a soft parse does - except it doesn't find a match so it
o optimizes (generate lots of plans, sort by cost, take the cheapest one)
o row source generates (turns plan into something that we can execute, generate byte code)
o puts it (new shared sql and row source) into the shared pool
o then execute

softer soft parse:
o peek at pointer, if sql still there in shared pool, reattach it then execute
o if sql not still there, goto hard/soft parse


excellent explanation

A reader, May 24, 2010 - 3:48 pm UTC

Many thanks Tom for your excellent explanation -

Sorry but one more doubt

there is a slight difference between any 3GL cached cursors and PL/SQL cached cursors ?

I was under impression if PL/SQL caches a curosr - the SQL can not be aged out(removed) from shared pool but for 3GL(client) cursors -Oracle will age out the SQL though the cursor is cached ?

Is it wrong assumption ?
Tom Kyte
May 24, 2010 - 7:44 pm UTC

... there is a slight difference between any 3GL cached cursors and PL/SQL cached
cursors ? ...

what is a 3gl cached cursor and how is pl/sql not a 3gl?

but most importantly, what do you mean by "3gl cached cursor", I'm not familiar with that term or concept.


A reader, May 25, 2010 - 4:43 am UTC


Sorry , I was wrong in saying '3gl cached cursors' - I meant to say any 'API' client which interacts with Database .

I want to know if there is difference between the caching mechanism between an API client caching and Pl/SQL caching .

PL/SQL will automatically 'caches' if the cursor is opened few times (say 3 times) but the API client - it depends on the API and user programming (the API code)- the client will decide whether to cache or not ,…

Is it correct ?
Tom Kyte
May 25, 2010 - 7:40 am UTC

define API client cache now. What is that? How is it implemented? What is it's logic?

See where I am going here - I don't know what API cache you are talking about, how it is implemented, what it does, how it was designed, how efficient it is. Every API would necessarily do it "their way"



PLSQL *does not* automatically cache the cursor if it is opened a few times - that is what SESSION_CACHED_CURSORS does for any client (any - repeat - any client).

PLSQL does it one better. When you open a cursor in PLSQL, and later close it (explicitly or implicitly), PLSQL keeps it OPEN - does not close it - right away, from the first time.

PLSQL will cache N open cursors like that (where N = setting for session_cached_cursors - but this is NOT using the session_cached_cursors logic at all, plsql just borrows that number to set N, that is all). If PLSQL has N cursors cached open - and the client has (OPEN_CURSORS-SESSION_CACHED_CURSORS - eg: N) cursors open (so that all possible cursors are opened - and the client attempts to open one more cursor - PLSQL will silently, transparently - close one of it's cursors (so now it has N-1 open) so the client can have OPEN_CURSORS-SESSION_CACHED_CURSORS+1 cursors open. PLSQL will keep doing that for as long as the client needs more cursor handles.


A reader, May 25, 2010 - 8:27 am UTC

Many Many thanks Tom for the excellent explanation ..
I am learning a lot of things *clearly* from you .

Sir , I have one question for you

Why do you revise and update your book 'Effective Oracle by design' ?

I have your book first edition (Expert Oracle architecture 9i and 10g) and got the alpha version of your second edition (Expert Oracle architecture 9i,10g and 11g ) and compared both of them - I may be wrong - what I have understood is you added just few 11g features of those concepts to the same old book .
But the one who ** understands clearly your first edition** can easily understands 11g features just by going through the concepts guide or any other book
Because that first book has basic, solid and great explanations for every concept- I don’t see very much benefit for going for second edition of the book while I have the first edition .

What thought came to mind is - if you rewrite the "Effective Oracle by design for 11g" - that would *rock and roll*..
Can we expect this in future ?

Sir, Please don’t mind - this is purely my personal opinion and this is what I felt in my mind.

Tom Kyte
May 25, 2010 - 12:37 pm UTC

the 2nd edition of Expert Oracle Database Architecture is an update - a 2nd edition. Corrections, updates to how things work now, some new features are included. But yes, by and large, it is still Expert Oracle Database Architecture - just the 2nd edition.

I just wrote on another thread a few minutes ago - that I would not actually change very much in Effective Oracle by Design - it wasn't really version specific in most of the pages - not at all. In fact, it would have made sense in version 7.3 for the most part...


How to close cursors...

Abhisek, September 07, 2010 - 10:25 am UTC

Hi Tom,

In case I declare a cursor in my package and I dont close it, what happens? Is it closed after some time automatically?

If not, I would like to know the way we can close the cursors that are open which I see through your query:

select sum(a.value), b.name
      from v$sesstat a, v$statname b
     where a.statistic# = b.statistic#
       and b.name = 'opened cursors current'
     group by b.name


Does the same logic applies for the CFL (Cursor For-Loop) also? as we dont fetch there, I hope.

Please suggest.
Tom Kyte
September 09, 2010 - 8:19 pm UTC

it depends, there are implicit cursors (always closed as they go out of scope - and they always go out of scope). there are explicit cursors - they do not always go out of scope, you would have to make sure that the ones that do not go out of scope are closed by you!

ops$tkyte%ORA11GR2> create or replace package my_pkg
  2  as
  3          procedure p;
  4  end;
  5  /

Package created.

ops$tkyte%ORA11GR2> 
ops$tkyte%ORA11GR2> create or replace package body my_pkg
  2  as
  3  
  4          cursor always_closed_for_me is select * from all_users;
  5  
  6          cursor I_must_close_this is select * from all_users;
  7  
  8  procedure p
  9  is
 10          cursor this_will_be_closed_for_me is select * from all_users;
 11          l_rec all_users%rowtype;
 12  begin
 13          for x in (select * from all_users THIS_IS_ALWAYS_CLOSED_FOR_ME)
 14          loop
 15                  null;
 16      end loop;
 17  
 18          for y in ALWAYS_CLOSED_FOR_ME
 19          loop
 20                  null;
 21          end loop;
 22  
 23          open I_must_close_this;
 24          loop
 25                  fetch I_must_close_this into l_rec;
 26                  exit when I_must_close_this%notfound;
 27          end loop;
 28          close I_must_close_this;
 29  
 30          open this_will_be_closed_for_me;
 31          loop
 32                  fetch this_will_be_closed_for_me into l_rec;
 33                  exit when this_will_be_closed_for_me%notfound;
 34          end loop;
 35          /* sloppy but I don't have to close it */
 36  end;
 37  
 38  end;
 39  /

Package body created.

A reader, September 10, 2010 - 9:33 am UTC

Dear Sir,


Nice example!!!


for x in (select * from all_users THIS_IS_ALWAYS_CLOSED_FOR_ME) ------- implicit cursor
14 loop
15 null;
16 end loop;
17
18 for y in ALWAYS_CLOSED_FOR_ME ----- declare in package body
19 loop
20 null;
21 end loop;


(1) so does it mean that explicit or imlicit cursor when loop through FOR LOOP will close implicitly i.e. automatically?


(2) Also when cursor is close implicitly OR explicitly does oracle still keep it open under the hood in PL/SQL cache ?


Thanks
Tom Kyte
September 13, 2010 - 7:46 am UTC

(1) yes.

(2) yes. up to session_cached_cursors in 9i and above (open_cursors in 8i and before)

Wierd open cursors current value

Dayne Olivier, October 28, 2010 - 4:51 am UTC

Hi Tom, (Oracle 10.1.0.5, open_cursors=300, session_cached_cursors=0, cursor_sharing=EXACT)

I stumbled upon something really strange today. It relates to open cursors. I was trying to determine how many open cursors were being used by each user (across multiple sessions), so I used the following SQL:
select sum(a.value) total_cur, avg(a.value) avg_cur, max(a.value) max_cur, count(*) sessions#,
s.username, s.machine, s.program
from v$sesstat a, v$statname b, v$session s 
where a.statistic# = b.statistic#  and s.sid=a.sid
and b.name = 'opened cursors current' 
group by s.username, s.machine, s.program
order by 1 desc;


This seemed to work quite well. I tested it by logging in and opening some cursors and closing some cursors etc. This seemed to work as expected.

However, while running this in my production environment, there was suddenly a single session that jumped to the top of the list with a number for total_cur that was so big, it just showed ############ as a value. So I quickly changed the query to try and get the total open cursors for the single user:
select a.value total_cur,
s.username, s.machine, s.program
from v$sesstat a, v$statname b, v$session s 
where a.statistic# = b.statistic#  and s.sid=a.sid
and b.name = 'opened cursors current'
AND S.USERNAME = 'HDM4' 

Using toad to view the output, I got a result of 1.84467440737096E19

And now, I am totally confused. I don't get it... How is this possible? There was only 1 session for the given schema (schema named 'HDM4'). A bit more info:
a) I also noticed that this was a dbms_job process.
b) The session seemed to be connected for perhaps 5-10 minutes.

Sanity check: is my SQL wrong?
How is it possible that the session opens more than open_cursors? And, is this query really indicating "currently open cursors"?

Thanks Tom
Tom Kyte
October 28, 2010 - 12:11 pm UTC

that looks like an overflow of some sort - please utilize support.

you could just:
select * 
  from v$sesstat
where sid in (select sid from v$session where username = 'HDM4')
and statistic# = (select statistic# from v$statname where name = 'opened cursors current' )

if you don't trust your join.

new book - suggestion only

Ajeet ojha, October 29, 2010 - 3:52 am UTC

Hi Tom,
have been asking questions here since last 8 yrs, some one above made a comment that you should write a new version of effective design for 11g. My opinion is you should write a book which tells more details..which help the mid-level experienced folks in oracle ( have 4-8 yrs of experience) mostly in consultiing work on oracle. reasons are :
1)There are so many un-answered queries in our mind - they never get answered - partly we don;t have source of information as we are not oracle employees - one such exmaple is - how to read AWR reports and make sense out of it. there are few things we know, we learn from asktom or we learn from some other books .
2) how to really approach a complex performance issue...

sometime i do feel that you just oversimplify the answers you gave here...I do unserstand that you speak from your experience and we will probably never reach to that level but there is fair amount of queroisity to know the things - how things actually work in oracle..to become more comptent than what we are.

recently i read a book "troubleshooting oracle performance" - something like that may be...if comes from you as well -would be a great assist .

Regards
Ajeet
Tom Kyte
November 01, 2010 - 5:06 am UTC

... sometime i do feel that you just oversimplify the answers you gave here... ...

No, I try to make the seemingly complex - simple. Which most of the times, it is. We tend to get buried in the details, not realizing that many things are actually "simple".

Fetched rows

Victor Hugo Marques COsta, June 21, 2013 - 8:36 pm UTC

Hi Tom!

Are there any way to know if a cursor still have any row to be fetched? I need to kill some inactive sessions with opened cursors, but I don´t know if one of these cursors will be fetched by the user later.

Thanks!
Victor
Tom Kyte
July 01, 2013 - 5:28 pm UTC

no, there isn't, not really. you could use the real time sql monitor to attach to the queries in 11g - but it would be rather clumsy to do this.


More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library