Chapter 10 · Shared Pool, Cursor Management, Bind Variables, and SQL Execution Lifecycle

Session Cursor Cache, Open Cursors, Parse Storms, and Shared Pool Contention

Separate OPEN_CURSORS, SESSION_CACHED_CURSORS, driver statement caches, and shared-pool memory; diagnose ORA-01000 and parse storms from session/system evidence before increasing limits.

Advanced120–140 minutesOpen/session-cache + ORA-01000 diagnosisOPEN_CURSORS and SESSION_CACHED_CURSORS separatedNo shared-pool flush; application leaks stay application bugsLast reviewed: August 2026

Learning outcomes

ServiceHub raises ORA-01000 in one connection pool, while another pool shows high parse CPU even though the shared SQL exists. An operator proposes increasing the shared pool, OPEN_CURSORS, and SESSION_CACHED_CURSORS together. Those settings govern different layers. This lesson separates open handles, cached closed session cursors, driver caches, and instance shared-pool code so each symptom gets the right repair.

01

Explain OPEN_CURSORS as a per-session simultaneous-open-handle limit rather than a shared-pool size.

02

Explain SESSION_CACHED_CURSORS as a cache of closed session cursors and measure session-cache hits.

03

Place application/driver statement caches above Oracle's session cursor cache without conflating their settings.

04

Diagnose ORA-01000 as either legitimate concurrent cursor demand or an application leak before raising the limit.

05

Measure parse storms and shared-pool contention signals without using FLUSH SHARED_POOL as a tuning action.

Version, tooling, licensing, scope, and privilege baseline

Mandatory examples target a disposable ServiceHub schema in Oracle AI Database Free 26ai and were reviewed against RU 23.26.3, SQL Developer 26.2, and SQLcl 26.2.1. Free is limited to 2 foreground CPUs, 2 GB combined SGA/PGA memory, and 12 GB user data and receives no Oracle patches or Support service requests. The mandatory path uses ordinary SQL, DBMS_STATS, session statistics, and dynamic performance views; it does not require AWR, ASH, SQL Monitor, Diagnostics Pack, or Tuning Pack. Where V$ views are queried, use a DBA observer or narrowly grant the corresponding V_$ fixed views in the disposable PDB rather than assigning broad catalog privileges. No lesson changes COMPATIBLE, hidden/underscore parameters, or the shared-pool size.

1. OPEN_CURSORS limits open private/session cursor handles

OPEN_CURSORS sets the maximum number of open cursor handles a session can have simultaneously. Current 26ai documents a default of 50, but production deployments often change it. A high setting does not preallocate the maximum for every session; the correct value depends on the application's legitimate concurrent open statements.

sql · inspect the current PDB/session-relevant value
SELECT name, value, isdefault, issys_modifiable, ispdb_modifiableFROM v$parameterWHERE name='open_cursors';

ORA-01000 means a session attempted to exceed this limit. It can be a real sizing issue, but Oracle's current error guidance explicitly identifies cursor leaks as a primary root cause. Raising the limit can postpone a leak without fixing it.

2. SESSION_CACHED_CURSORS caches closed session cursors for reuse

SESSION_CACHED_CURSORS controls how many closed session cursors Oracle can keep cached for that session. Current 26ai documents a default of 50 and allows ALTER SESSION or deferred system changes. The cache is independent of OPEN_CURSORS because cached session cursors are not held open.

Oracle's performance guide notes that after repeated parse requests for a statement, a closed cursor can become eligible for the session cursor cache. Reopening it can avoid some reparsing work. A cache hit is still reported as a parse call, but it is a much softer reuse path than rebuilding executable code.

sql · measure current-session cache and parse statistics
SELECT n.name, m.valueFROM v$mystat mJOIN v$statname n ON n.statistic#=m.statistic#WHERE n.name IN (  'session cursor cache count',  'session cursor cache hits',  'parse count (total)',  'parse count (hard)',  'opened cursors current',  'opened cursors cumulative')ORDER BY n.name;SELECT name, valueFROM v$parameterWHERE name IN ('open_cursors','session_cached_cursors')ORDER BY name;

3. Driver statement caches are another layer

JDBC, OCI, python-oracledb, ODP.NET, and other drivers/pools can cache prepared statements or cursor handles according to driver-specific rules. A driver statement cache can avoid repeated client/database prepare/open work; Oracle's session cursor cache can reuse closed session cursors; the library cache shares executable SQL across sessions. These are complementary layers, not duplicate names for one cache.

Layer Scope What it reuses
Application/driver statement cache Connection/pool/driver Prepared statement/cursor handles per driver implementation
Session cursor cache Database session Closed session cursors pointing to shared children
Library cache/shared SQL Instance SGA shared pool Parent/child executable/shared SQL areas

Always record the actual driver/version/cache configuration before changing database parameters.

4. Diagnose ORA-01000 from a separate observer connection

sql · sessions near the OPEN_CURSORS limit
SELECT    s.username,    s.sid,    s.serial#,    ss.value AS opened_cursors_current,    p.value  AS open_cursors_limitFROM v$sesstat ssJOIN v$statname sn  ON sn.statistic#=ss.statistic#JOIN v$session s  ON s.sid=ss.sidCROSS JOIN (    SELECT value FROM v$parameter WHERE name='open_cursors') pWHERE sn.name='opened cursors current'  AND s.username IS NOT NULLORDER BY ss.value DESC;
sql · which SQL texts are held open in one suspect session
SELECT    sid,    user_name,    sql_id,    cursor_type,    COUNT(*) AS open_cursor_entries,    substr(sql_text,1,120) AS sql_textFROM v$open_cursorWHERE sid=:suspect_sidGROUP BY sid,user_name,sql_id,cursor_type,substr(sql_text,1,120)ORDER BY open_cursor_entries DESC, sql_id;

V$OPEN_CURSOR is diagnostic evidence, not a direct leak detector by itself. Frameworks can legitimately keep prepared statements open. Correlate the count over time with request/connection lifecycle and application telemetry.

5. Deliberately wrong: solve ORA-01000 by multiplying the limit immediately

If a pool leaks ten cursors per request, increasing OPEN_CURSORS from 300 to 3000 only lets the leak run longer and consume more memory. The safe repair is to find the owning code path and close/reuse statements correctly. Increase the limit only if before/after observation proves the application legitimately needs more simultaneous opens.

Parameter change scope

OPEN_CURSORS is system-modifiable and PDB-modifiable; SESSION_CACHED_CURSORS is session/system-deferred and PDB-modifiable. Do not change either globally from one incident sample.

6. Parse storms are about rate and concurrency, not just hard-parse percentage

A parse storm is sustained excessive parse activity relative to useful executions, often from literal SQL, prepare/close loops, session-setting mismatches, or invalidations. Hard parse is especially expensive, but extremely high soft-parse rates can also burn CPU and contend on library-cache/mutex structures.

sql · instance-level parse counters — snapshot twice and calculate rates externally
SELECT name, valueFROM v$sysstatWHERE name IN (  'parse count (total)',  'parse count (hard)',  'parse time cpu',  'parse time elapsed',  'execute count')ORDER BY name;

A cumulative counter without a time interval is not a rate. Capture two timestamps around a representative window and compute deltas. Pair the database evidence with request throughput and application statement-cache metrics.

7. Do not flush the shared pool as a tuning technique

ALTER SYSTEM FLUSH SHARED_POOL can invalidate the very evidence you need and forces unrelated SQL to reload/hard parse. It can create an artificial CPU spike and make a transient plan/cursor problem look “fixed” until the workload repopulates the cache. Use it only for narrowly justified administrative/test purposes, not as incident treatment.

8. Hands-on lab: session cursor cache behavior without changing system settings

Run this in a disposable SQLcl/SQL*Plus session. Record the original session setting first and restore it afterward.

sql · record and temporarily change only this session
SELECT value AS original_session_cached_cursorsFROM v$parameterWHERE name='session_cached_cursors';ALTER SESSION SET session_cached_cursors=20;
sql · repeat open/close behavior through dynamic SQL
DECLARE  n NUMBER;BEGIN  FOR pass IN 1..8 LOOP    FOR i IN 1..10 LOOP      EXECUTE IMMEDIATE        'SELECT /* sh10_l4_cache */ COUNT(*) FROM dual WHERE :x=:x'        INTO n        USING i, i;    END LOOP;  END LOOP;END;/
sql · inspect this session after the workload
SELECT n.name, m.valueFROM v$mystat mJOIN v$statname n ON n.statistic#=m.statistic#WHERE n.name IN (  'session cursor cache count',  'session cursor cache hits',  'parse count (total)',  'parse count (hard)',  'opened cursors current')ORDER BY n.name;

Restore the original value from your recorded evidence. Do not assume 20 or 50 is appropriate for production; sizing depends on the repeated working set and parse/cache-hit evidence.

9. Production judgment

When ORA-01000 appears, determine whether the application legitimately holds many concurrent statements or leaks them. When parse CPU is high, determine whether SQL text changes, close/reparse behavior, invalidation, optimizer-environment drift, or child proliferation is responsible. Tune driver statement caches and session cursor caching with measured hit/reuse behavior; size OPEN_CURSORS for legitimate concurrency after code is correct.

No restart, management pack, or COMPATIBLE change is needed for the mandatory lab. Lesson 5 combines the chapter into an incident workflow: deliberately create a child-cursor mismatch, explain it with V$SQL_SHARED_CURSOR, normalize session settings, and prove stabilization with parse/child evidence.

Check your understanding

  1. What does OPEN_CURSORS limit?
  2. Can SESSION_CACHED_CURSORS be larger than OPEN_CURSORS?
  3. Why might increasing OPEN_CURSORS fail to fix ORA-01000 permanently?
  4. Is a session cursor cache hit invisible to parse-count statistics?
  5. Why is FLUSH SHARED_POOL a poor tuning response?
Review the answers

It limits the number of cursor handles/private SQL areas a session can have open simultaneously.

Yes. Cached session cursors are closed, so the two parameters are independent.

A leaking application can simply consume the larger allowance; fix/verify statement lifecycle first.

No. Oracle documents that reuse from the session cursor cache still registers as a parse, although it avoids a hard parse/reparse path.

It destroys useful evidence and causes unrelated SQL to reload/hard parse without repairing the root cause.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.