问题:即使使用连接池,也有很多与数据库建立的活动未关闭物理连接。有人可以告诉我为什么会这样吗?
我使用oracle.jdbc.pool.OracleDataSource
配置了连接池设置。然而,似乎物理连接在使用后没有关闭。
我想,由于它是连接池,连接将从池中重用,因此将不会进行如此多的物理连接,
但那不是现在发生的事情!
从应用程序生成的数据库中有100多个活动物理连接[不是来自plsql开发人员或任何此类客户端工具], 由于它在尝试对数据库进行写操作时启动TNS错误, 即使有大量活动连接,读操作也很好。
这是Spring配置,
<bean id="oracleDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close"
p:URL="${url}"
p:user="${username}"
p:password="${password}"
p:connectionCachingEnabled="true">
<property name="connectionProperties">
<props merge="default">
<prop key="AutoCommit">false</prop>
</props>
</property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
p:dataSource-ref="oracleDataSource" />
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="oracleDataSource">
</bean>
返回100多个活动连接的SQL是
select username, terminal,schemaname, osuser,program from v$session where username = 'grduser'
答案 0 :(得分:1)
您应该配置连接缓存,隐式连接缓存的最大连接的默认值是为数据库配置的最大数据库会话数。
答案 1 :(得分:0)
感谢@Evgeniy Dorofeev。
详细解决方案:
`
<bean id="oracleDataSource" class="oracle.jdbc.pool.OracleDataSource" destroy-method="close"
p:URL="${url}"
p:user="${username}"
p:password="${password}"
p:connectionCachingEnabled="true">
<property name="connectionProperties">
<props merge="default">
<prop key="AutoCommit">false</prop>
</props>
</property>
<property name="connectionCacheProperties">
<props>
<prop key="MinLimit">5</prop>
<prop key="MaxLimit">10</prop>
<prop key="InactivityTimeout">2</prop>
</props>
</property>
</bean>
`
现在,对于需要连接的应用程序中的每个操作,它将尝试从池中获取并且可以使用,但保证数据库最多只有10个活动物理连接。任何获得额外物理连接的尝试都会导致应用程序端出现数据库错误。
connectionCache
,也请确保您的应用未明确尝试获取连接,例如 Connection connection = getJdbcTemplate().getDataSource().getConnection();
这是令人担忧的,JDBCTemplate不会管理此连接的关闭。因此,您必须在使用后自行关闭,否则即使在使用后,物理连接仍将处于活动状态且未关闭。因此,下次再次调用它时,它会尝试获取新的物理连接,并保持未闭合状态,从而导致堆积活动连接,直到达到maxLimit为止。
当你想将它作为参数传递给其他函数时,可能需要明确连接,例如在ArrayDescriptor的情况下[如果你谈到具有IN参数的PLSQL存储过程来接受一个值数组, Varchar数组或RAW数组]。如果需要创建ArrayDescriptor,
ArrayDescriptor arrayDescriptor = ArrayDescriptor.createDescriptor(
"SOME_TYPE_NAME", connection );
ARRAY SQLArray= new ARRAY(arrayDescriptor, connection , arrayString);
因此,这里明确表达connection.close()
。
其他信息:
Connection connection = getJdbcTemplate().getDataSource().getConnection()
调用这行代码 - 一次,将尝试建立新连接。 再次呼叫,将建立第二个连接。对于每个请求,它将创建一个新连接!。如果你的maxLimit是10, 在数据库中有10个活动物理连接之前,呼叫将成功,但是 请注意,所有连接都处于活动状态[未关闭]。
因此,现在假设有10个活动数据库连接,因为maxLimit设置为10。
所以任何需要数据库操作的请求都会通过 通过JDBCTemplate访问连接的正常路由将从[10个连接]中获取已建立的连接
但是,任何调用此代码getJdbcTemplate().getDataSource().getConnection()
来访问连接的请求
将尝试建立新连接,并将失败,导致异常。
解决此问题的唯一方法是在显式创建连接时显式关闭连接。
即呼叫connection.close()
当我们没有明确地创建连接时,以及当它由Spring管理时,Spring将负责关闭
连接也是。在使用Oracle数据源池和JDBCTemplate
的情况下,关闭连接[返回
连接到池]由Spring管理。