The patch set 11.2.0.3 includes a fix for bug# 10187168 which, in reality, is an enhancement request. Its purpose is to artificially limit the number of child cursors that a parent cursor can have. The concept is quite easy: when a parent cursor reaches _cursor_obsolete_threshold (default value is 100) child cursors the parent cursor is obsoleted and, as a result, a new one is created.

So, as of 11.2.0.3 (or with some PSUs and bundle patches), the answer to the question is: 100.

But how many child cursors are supported in previous 11.2 releases? This is a question that crossed my mind few weeks ago while preparing for the “Shareable Cursors” presentation that I gave at the OakTable World in San Francisco. Is it for example possible to have a parent cursor with 1,000,000 child cursors? Not that something like that is sensible, but I would like to know whether it is technically possible. In other words, whether the database engine supports it.

To try answering the question, I wrote and run on 11.2.0.2 the following test case. Notice that the PL/SQL block is able, if there is enough memory, to create 1,000,000 child cursors. Hence, before running it, I increased the shared pool size to 10GB.

SQL> CREATE TABLE t (n NUMBER);

Table created.

SQL> INSERT INTO t VALUES (1);

1 row created.

SQL> COMMIT;

Commit complete.

SQL> execute dbms_stats.gather_table_stats(user,'t')

PL/SQL procedure successfully completed.

SQL> DECLARE
  2    l_count PLS_INTEGER;
  3  BEGIN
  4    FOR oic IN 1..100
  5    LOOP
  6      EXECUTE IMMEDIATE 'ALTER SESSION SET optimizer_index_caching = '||oic;
  7      FOR oica IN 1..10000
  8      LOOP
  9        EXECUTE IMMEDIATE 'ALTER SESSION SET optimizer_index_cost_adj = '||oica;
 10        EXECUTE IMMEDIATE 'SELECT count(*) FROM t' into l_count;
 11      END LOOP;
 12    END LOOP;
 13  END;
 14  /
DECLARE
*
ERROR at line 1:
ORA-03113: end-of-file on communication channel
Process ID: 6809
Session ID: 7 Serial number: 9

As you can see the result is interesting ;-)

In the alert.log I found the following information:

Errors in file /u00/app/oracle/diag/rdbms/dbm11202/DBM11202/trace/DBM11202_ora_6809.trc  (incident=25425):
ORA-00600: internal error code, arguments: [15206], [], [], [], [], [], [], [], [], [], [], []
Incident details in: /u00/app/oracle/diag/rdbms/dbm11202/DBM11202/incident/incdir_25425/DBM11202_ora_6809_i25425.trc

As always, when I see this kind of error, I check the ORA-600/ORA-7445/ORA-700 Error Look-up Tool. Unfortunately, in this case, no information is provided. So I continued investigating the issued by looking at the trace file generated for the incident. As expected the SQL statement hitting the problem was the following:

----- Current SQL Statement for this session (sql_id=5tjqf7sx5dzmj) -----
SELECT count(*) FROM t

And the library cache content for the associated cursor was the following:

      LibraryHandle:  Address=0x2c5e4d030 Hash=3a56fe71 LockMode=N PinMode=0 LoadLockMode=0 Status=VALD
        ObjectName:  Name=SELECT count(*) FROM t
          FullHashValue=6d0bd54734bada875cc6ce3e3a56fe71 Namespace=SQL AREA(00) Type=CURSOR(00) Identifier=978779761 OwnerIdn=36
        Statistics:  InvalidationCount=0 ExecutionCount=65535 LoadCount=65536 ActiveLocks=51 TotalLockCount=65536 TotalPinCount=1
        Counters:  BrokenCount=1 RevocablePointer=1 KeepDependency=65535 BucketInUse=0 HandleInUse=0 HandleReferenceCount=0
        Concurrency:  DependencyMutex=0x2c5e4d0e0(0, 4097, 0, 0) Mutex=0x2c5e4d160(0, 5120057, 12919, 0)
        Flags=RON/PIN/TIM/PN0/DBN/[10012841]
        WaitersLists:
          Lock=0x2c5e4d0c0[0x2c5e4d0c0,0x2c5e4d0c0]
          Pin=0x2c5e4d0a0[0x2c5e4d0a0,0x2c5e4d0a0]
        Timestamp:  Current=10-19-2012 07:02:48
        HandleReference:  Address=0x2c5e4d1e0 Handle=(nil) Flags=[00]
        LibraryObject:  Address=0x2c5e4bfc0 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
          ChildTable:  size='65536'
            Child:  id='0' Table=0x2c5e4ce70 Reference=0x2c5e4c898 Handle=0x2c5e4bbd0
            Child:  id='1' Table=0x2c5e4ce70 Reference=0x2c5e4cd58 Handle=0x2c5dd4338
            Child:  id='2' Table=0x2c5e4ce70 Reference=0x2c5dce0d0 Handle=0x2c5dcdae8
            Child:  id='3' Table=0x2c5e4ce70 Reference=0x2c5dce568 Handle=0x2c5dc8298
            Child:  id='4' Table=0x2c5e4ce70 Reference=0x2c5dcea00 Handle=0x2c5dc2a48
            …
            Child:  id='65530' Table=0x2846e56d8 Reference=0x2846b07e8 Handle=0x2846b03d8
            Child:  id='65531' Table=0x2846e56d8 Reference=0x2846b0c80 Handle=0x2846ad188
            Child:  id='65532' Table=0x2846e56d8 Reference=0x2846b1118 Handle=0x2846a9f38
            Child:  id='65533' Table=0x2846e56d8 Reference=0x2846a60f8 Handle=0x2846a5ce8
            Child:  id='65534' Table=0x2846e56d8 Reference=0x2846a6590 Handle=0x2846a2a98

The most interesting part is the one providing the number of child cursors: 65536.

I might be wrong but to me that means that the child number is stored as an unsigned integer taking 16 bits. And, when the maximum is exceeded, an ORA-00600 is raised.

According to this test the maximum number of child cursors for a given parent cursor is 65536. But, as already written, the fix for bug# 10187168 artificially limits it to 100.