У меня проблема в том, что мое Java-приложение экспортирует большее количество clobs из базы данных, но всегда не хватает временного табличного пространства, поскольку старые clobs не освобождаются.
Упрощенный пример кода, как я это делаю:
public void getClobAndDoSomething (oracle.jdbc.OracleCallableStatement pLSQLCodeReturningClob) {
try (OracleCallableStatement statement = pLSQLCodeReturningClob) {
statment.registerOutParameter(1, Types.CLOB);
statement.execute();
oracle.sql.CLOB clob = statement.getCLOB(1);
clob.open(CLOB.MODE_READONLY);
Reader reader = clob.getCharacterStream();
BufferedReader bufferedReader = new BufferedReader(reader);
doSomethingWithClob(bufferedReader);
bufferedReader.close();
reader.close();
clob.close();
clob.freeTemporary();
} catch (SQLException e) {
if (e.getErrorCode() == 1652) {
//Server ran out of temporary tablespace
} else
handleException(e);
} catch (IOException e) {
handleException(e);
}
}
Если этот метод вызывается в цикле, в какой-то момент ему всегда будет не хватать временного табличного пространства.
Единственный надежный способ освободить место — закрыть соединение и открыть новое (например, с помощью clob.getInternalConnection.close()
), но это замедлит работу приложения и сделает текущий многопоточный подход непригодным для использования.
К сожалению, документация оракула на ojdbc не очень полезна, и Google нашел только статьи, в которых мне предлагалось использовать метод free()
лобов, который даже не реализован во временных клобах оракулов.
Дополнительное примечание.
Эта проблема также возникает при использовании оракулов APEXExport.class
для экспорта большой рабочей области.
Особенности драйвера и системы:
- ОС: Windows 7 Профессиональная x64
- Java: 1.8.0_45 64-разрядная версия
- ojdbc: 6 (Есть более конкретные версии?)
- База данных: Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 — 64-битная производственная версия
Тестовый код, если у вас есть APEX-приложение:
java.sql.Connection con = getConnection();
String gStmtGetAppClob = "begin ? := wwv_flow_utilities.export_application_to_clob(?, ?, ?, ?); end;";
int appId = 100;
while (true) {
OracleCallableStatement exportApplicationToClob = (OracleCallableStatement) con.prepareCall(gStmtGetAppClob);
exportApplicationToClob.setString(3, "Y"); //Public reports
exportApplicationToClob.setString(4, "N"); //Saved reports
exportApplicationToClob.setString(5, "N"); //Interactive report notifications
exportApplicationToClob.setBigDecimal(2, new BigDecimal(appId));
getClobAndDoSomething(exportApplicationToClob);
try {
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
con.close();
Обновление:
После дополнительного тестирования я обнаружил, что в какой-то момент clobs освобождаются без закрытия соединения. Так что похоже, что free()
на самом деле lazyFree()
. Но это может занять больше минуты.
Я также могу преобразовать CLOB в Clob, не знаю, что я раньше делал не так. Проблема остается неизменной при использовании Clob.
free()
также выполняется в случае исключения! - person Lukas Eder   schedule 14.08.2015free()
в блоке catch. В пример не вставил. К сожалению, я не могу использовать стандартный JDBC API, так как БД возвращает временный файл. Стандартный JDBC может обрабатывать только клобы, хранящиеся в таблице. (Приведение или преобразование приводит к исключению) - person Simon M   schedule 14.08.2015