#jdbc #memory-leaks #prepared-statement #oracle12c #apache-commons-dbcp
#jdbc #утечки памяти #подготовленный оператор #oracle12c #apache-commons-dbcp
Вопрос:
Использование пула соединений DBCP2 в веб-приложении spring с Oracle 12c r1 в качестве серверной базы данных с OJDBC8.jar , включил функцию poolpreparedstatement в dbcp2, чтобы уменьшить синтаксический анализ на стороне базы данных.
Конфигурация DBCP2:
String data = property.getProperty(Constants.DATABASE_USERNAME);
if( data != null amp;amp; data.isEmpty() == false )
setUsername(data);
setPassword(password);
data = property.getProperty(Constants.DATABASE_INITIAL_SIZE);
if( data != null amp;amp; data.isEmpty() == false )
setInitialSize(Integer.parseInt(data));
else
setInitialSize(8);
data = property.getProperty(Constants.DATABASE_MAX_ACTIVE);
if( data != null amp;amp; data.isEmpty() == false )
setMaxTotal(Integer.parseInt(data));
else
setMaxTotal(64);
this.setPoolPreparedStatements(true);
this.setMaxOpenPreparedStatements(120);
При установке количества подготовленных операторов для параметра пула на значение > 100 и выполнении пакетных вставок с использованием BatchSqlUpdate в таблицу M1 (например), через определенное время приложение завершает работу с javaOutofMemory: java heap exception .
Таблица desc:
c1 NOT NULL NUMBER(38)
c2 NOT NULL NUMBER(38)
c3 NOT NULL NUMBER(38)
c4 NOT NULL NUMBER(38)
c5 NUMBER(38)
c6 NUMBER(38)
c7 RAW(2000 BYTE)
c8 RAW(2000 BYTE)
c9 BLOB
Посмотрел на v $ sql_shared-cursor view, чтобы увидеть version_count . Но из-за несоответствия привязки в maxlength в одном из 3 столбцов двоичного типа данных учитывается только 3 версии. Нет большого количества версий, поэтому перешел,
Просмотрел дамп кучи, чтобы найти этот oracle.T4CPreparedStatement сохраняет большие объемы памяти в:
это значение: oracle.jdbc.driver.T4CPreparedStatement #143 -> parameterStream — class: oracle.jdbc.driver.T4CPreparedStatement, значение: java.io.InputStream[][] #2—-> ЭТО ВМЕЩАЕТ В СЕБЯ МНОГО ПАМЯТИ
Экземпляр T4CPreparedStatement предназначен для следующего запроса: запрос запущен, как показано в v $ sql_area и heapdump:
Insert into M1(c1,c2,c3,c4,c5,c6,c7,c8,c9) values(:1,:2,:3,:4,:5,:6,:7,:8,:9)
Фактически все экземпляры, которые сохраняют большой объем памяти, предназначены для одного и того же оператора insert, подготовленного в таблице M1.
Еще одна вещь, которую я заметил, это то, что количество экземпляров инструкции oracleT4CPrepared и PooledPreparedStatement dbcp2 совпадают и составляют 631 экземпляр, хотя я установил максимальное значение 120
Обратите внимание, что это происходит не всегда последовательно, иногда экземпляры T4CPreparedStatement удаляются из памяти, как видно в последовательных дампах кучи, и приложение продолжает работать.
Как я могу освободить память, хранящуюся в oracle preparedstatement?