Description
Carsten Jahn opened SPR-6209 and commented
We were facing an issue which the temp tablespace being used more and more while CLOBs were fetched in the application.
There are two kinds of LOBs: "ordinary" LOBs and temporary LOBs. Temporary LOBs are constructed on the fly, e.g. while processing a select that appends to LOBs to each other (e.g. molformula || molformula) or functions that create LOBs (e.g. molfile(ctab) returns a temporary CLOB). Temporary CLOBs need to be stored somewhere until they are not needed any more, and they are stored in the TEMP tablespace.
From the Oracle documentation on "Working With Temporary LOBs":
http://download.oracle.com/docs/cd/B28359_01/java.111/b31224/oralob.htm#i1060097
"When fetching data from a ReultSet with columns that are temporary LOBs, use getClob or getBlob instead of getString or getBytes. Also invoke freeTemporary to free the temporary LOBs."
This practice is not implemented in OracleLobHandler. It has methods like
public String getClobAsString(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning Oracle CLOB as string");
Clob clob = rs.getClob(columnIndex);
return (clob != null ? clob.getSubString(1, (int) clob.length()) : null);
}
that should better be implemented that way:
public String getClobAsString(ResultSet rs, int columnIndex) throws SQLException {
logger.debug("Returning Oracle CLOB as string");
oracle.sql.CLOB clob = (oracle.sql.CLOB) rs.getClob(columnIndex);
String returnString = (clob != null ? clob.getSubString(1, (int) clob.length()) : null);
if( clob.isTemporary() ) {
clob.freeTemporary();
}
return returnString;
}
I think that all getClob* / getBlob* methods are affected, although I just tested the change that I pasted above. It works for me, the TEMP tablespace does not get used much and I can fetch large amounts of records with temporary CLOBs - that was not possible before, I just got "ORA-01652: unable to extend temp segment by 128 in tablespace TEMP" after some time.
To reproduce, I think you need a sufficiently small TEMP tablespace, and a SELECT statement that returns large temporary CLOBs, e.g. by appending columns with || and returning the append result.
Without this fix, TEMP tablespace is freed only after Oracle session termination.
Affects: 2.5.6, 3.0 RC1
Issue Links:
- Memory Leak in Oracle LOB Reading?? [SPR-5998] #10666 Memory Leak in Oracle LOB Reading??
Referenced from: commits 5a158fb