[英]Oracle data source connection pooling not working used with Spring and JDBCTemplate
問題:即使有連接池,也有很多與數據庫的活動未閉合物理連接。 有人能告訴我為什么會這樣嗎?
我使用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'
您應該配置連接緩存,隱式連接緩存的最大連接的默認值是為數據庫配置的最大數據庫會話數。
感謝@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管理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.