A “blast from the past” was recently updated by Oracle Support; it involves a subpool memory leak in Oracle 11.2.0.1 and shared cursors. Originally submitted in 2010 this issue was updated this year to reflect the status of ‘Fixed in Product Version 12.1’. There have been several bug fixes to the 11.2.0 series of releases addressing this and similar issues, but I suspect Oracle Support waited for it’s declaration of ‘fixed’ until 12.1.0.2 was released. Let’s look at the symptoms and how you can investigate the shared pool subpools without generating a trace file.
The issue finally becomes apparent when an ORA-04031 error is thrown:
ORA-4031: unable to allocate ... bytes of shared memory ("shared pool","STANDARD","PLMCD^e93dbe75","BAMIMA: Bam Buffer")
In the original submission a trace file for the 4031 error, generated by the database, was submitted which revealed the offending portion of subpool 2:
Memory Utilization of Subpool 1
================================
"free memory " 25488576
"SQLA " 134248904
"PCUR " 25094632
Memory Utilization of Subpool 2
================================
"free memory " 127129872
"PCUR " 2427488432
Notice that the PCUR area in subpool 2 is almost 100 times the size of the same area in subpool 1. Unfortunately an AWR report shows only the Shared Pool Size, not a breakdown of the various subpools in the Shared Pool. Fortunately Tanel Poder has provided a tool to print out the various memory segments in the subpools called sgastatx.sql that can be used to see how much memory is allocated to each subpool by reporting on all of the memory areas of interest. Looking at an example of how the script is run:
SQL> @sgastatx %
-- All allocations:
SUBPOOL BYTES MB
------------------------------ ---------- ----------
shared pool (0 - Unused): 83886080 80
shared pool (1): 184549376 176
shared pool (Total): 268435456 256
-- Allocations matching "%":
SUBPOOL NAME SUM(BYTES) MB
------------------------------ -------------------------- ---------- ----------
shared pool (0 - Unused): free memory 83886080 80
shared pool (1): free memory 41599128 39.67
SQLA 14559048 13.88
KGLH0 12547880 11.97
row cache 8641136 8.24
KGLS 7616536 7.26
db_block_hash_buckets 5836800 5.57
KGLSG 5267216 5.02
dbwriter coalesce buffer 4194816 4
KCB Table Scan Buffer 4194816 4
kglsim hash table bkts 4194304 4
...
The default behavior of the script is to report everything, so the % parameter is not necessary. Other text parameters can be passed to return memory areas of concern, in this case the KGLH0 area, which maps to the PCUR data reported in the trace file. Returning only the KGLH0 allocations:
SQL> @sgastatx KGLH0
-- All allocations:
SUBPOOL BYTES MB
------------------------------ ---------- ----------
shared pool (0 - Unused): 83886080 80
shared pool (1): 184549376 176
shared pool (Total): 268435456 256
-- Allocations matching "KGLH0":
SUBPOOL NAME SUM(BYTES) MB
------------------------------ -------------------------- ---------- ----------
shared pool (1): KGLH0 12560024 11.98
SQL>
In the database used for these runs only one subpool is allocated outside of subpool 0, which is the free memory not yet allocated to a subpool. As allocations to various supheaps are made subpool 0 decreases in size until all of the unallocated free space is consumed. This can result in ‘lopsided’ allocations to some subpools; once memory is allocated to a particular subpool it cannot be re-allocated to another subpool. In ‘normal’ cases when ORA-04031 errors arise, expanding the shared pool will correct them, provided dynamic shared pool allocations are configured by setting sga_max_size larger than sga_target. In extreme cases, such as this memory leak, the only solution is to restart the database to clear out the existing memory segments. The sgastatx.sql script can be run at any time, won’t impact performance and will provide the current allocations allowing the DBA to monitor the subpool segments so proactive changes can be made to prevent ORA-04031 errors, again provided dynamic shared pool allocations are configured.
The sgastatx.sql script can also report on the free space in all allocated subpools as well as in subpool 0:
SQL> @sgastatx "free memory"
-- All allocations:
SUBPOOL BYTES MB
------------------------------ ---------- ----------
shared pool (0 - Unused): 83886080 80
shared pool (1): 184549376 176
shared pool (Total): 268435456 256
-- Allocations matching "free memory":
SUBPOOL NAME SUM(BYTES) MB
------------------------------ -------------------------- ---------- ----------
shared pool (0 - Unused): free memory 83886080 80
shared pool (1): free memory 37168136 35.45
SQL>
When subpool 0 is exhausted it will be eliminated from the displayed output, which will indicate that Oracle can make no more adjustments to the existing subpools and either a dynamic shared pool increase needs to be executed or failing that, the spfile needs to be changed, the database stopped and then restarted. [If an spfile is not in use then the pfile needs to be modified to reflect the memory increase, followed by a shutdown and startup of the database. For ease of administration it is recommended that an spfile, rather than a pfile, be used.]
The ideal solution to this issue is to either patch to the terminal release of 11.2.0 (11.2.0.5) or upgrade to 12.1.0.2 so the memory-related bugs can be patched. It is possible that a third-party application may not be certified for any release newer than 11.2.0.1 (which should be an extremely rare case) then the next solution is to apply relevant patches for 11.2.0.1. Oracle Support lists eight merge patches for bug fixes related to this memory leak (18730652, 18837746, 18980005, 19015163, 19494335, 19481242, 21078557 and 21076074).
I hope that those running on the base version 11.2.0.1 are few and far between, but anything is possible. Being prepared is the best way a DBA can quickly and reliably address issues, even those needing a bit of research.