Использование пула соединений DBCP2 в весеннем веб-приложении с Oracle 12c r1 в качестве внутренней базы данных с OJDBC8.jar, включило функцию подготовленного пула в dbcp2, чтобы уменьшить разбор на стороне базы данных.
Конфигурация DBCP2:
String data = property.getProperty(Constants.DATABASE_USERNAME);
if( data != null && data.isEmpty() == false )
setUsername(data);
setPassword(password);
data = property.getProperty(Constants.DATABASE_INITIAL_SIZE);
if( data != null && data.isEmpty() == false )
setInitialSize(Integer.parseInt(data));
else
setInitialSize(8);
data = property.getProperty(Constants.DATABASE_MAX_ACTIVE);
if( data != null && data.isEmpty() == false )
setMaxTotal(Integer.parseInt(data));
else
setMaxTotal(64);
this.setPoolPreparedStatements(true);
this.setMaxOpenPreparedStatements(120);
При установке числа подготовленных операторов для параметра пула на значение> 100 и выполнении пакетных вставок с использованием BatchSqlUpdate в таблицу M1 (например), по истечении определенного времени происходит сбой приложения с javaOutofMemory: исключение кучи java.
Таблица описания:
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, чтобы увидеть version_count. Но существует только 3 версии из-за несоответствия привязки по максимальной длине в одном из 3 столбцов двоичного типа данных. Никакое старшее число не было перенесено,
Посмотрев на дамп кучи, обнаружил, что oracle.T4CPreparedStatement сохраняет большие объемы памяти в:
this - значение: oracle.jdbc.driver.T4CPreparedStatement # 143
-> parameterStream - класс: 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)
Infact все экземпляры, которые сохраняют большой объем памяти, для точно такой же подготовленный оператор вставки в таблице M1.
Еще одна вещь, которую я заметил, это число экземпляров oracleT4CPrepared Statement и PooledPreparedStatement в dbcp2 совпадают и составляют 631 экземпляр, хотя я установил maxlimit как 120
Обратите внимание, что это не всегда происходит последовательно, иногда экземпляры T4CPreparedStatement удаляются из памяти, как видно из последовательных дампов кучи, и приложение продолжает работать.
Как мне освободить память, которую держит подготовленное оракулом заявление?