在Spring中基於JDBC進行數據訪問時如何控制超時


超時分類

超時根據作用域可做如下層級划分:

Transaction Timeout > Statement Timeout > JDBC Driver Socket Timeout
Transaction Timeout指一組SQL操作執行時應在設定的時間內完成(提交或回滾),否則將引發超時。它的值應大於 N(語句數) * Statement Timeout
Statement Timeout指完成單條SQL語句執行的最大允許時間。它的值應小於JDBC Driver Socket Timeout的值,因為后者會被先檢查。
最底層的JDBC Driver Socket Timeout指的是通過socket進行連接時的超時或者進行讀寫操作時的阻塞超時,如果不設置將使用OS層的Socket Timeout值。

超時設置
大部分場景中,應用主要關心Transaction Timeout的設置,除非Transaction中總是只有單條Statement。超時的具體設置依賴於使用的數據訪問框架或者JDBC Driver。如果使用Spring作為基礎框架,可以通過為transactionManager的defaultTimeout屬性來設置全局的Transaction Timeout,或者在聲明式事務(tx:attributes)的配置中為特定的或所有的方法指定timeout屬性的值,還可以在注解式事務@Transactional標記中通過timeout參數來設置。
注意:
1.“ Spring事務超時 = 事務開始時到最后一個Statement創建時時間 + 最后一個Statement的執行時超時時間(即其queryTimeout)。”(3)
2. 如果選擇JpaTransactionManager作為事務管理器,需要Spring版本在3.0.0之上才能使timeout設置正常工作;
3. 如果選擇DataSourceTransactionManager,事務內所有的sql操作必須通過JdbcTemplate執行才能使timeout設置正常工作,通過其他orm(如myBatis)執行的sql操作將無法應用超時設置。這種模式下需要按照具體orm框架的要求配置超時(例如myBatis的defaultStatementTimeout 4)
 
在某些場景中,確實存在混用兩種數據訪問框架的情況(姑且不討論這種情況是否合理)。例如在同一事務中混用JdbcTemplate和MyBatis,在這種場景中,為@Transactional或tx:attributes設置的timeout將不會對非JdbcTemplate部分的操作生效,因此實際上已無法控制這個事務的超時。此時,有一種“變通”的方式能夠使兩種數據訪問框架能夠“共享”超時設置,那就是設置JDBC Driver Socket阻塞超時。如果使用的是Oracle數據庫,並且數據源使用的是DBCP的BasicDataSource,可以在其connectionProperties屬性中設置此值,例如:
 
 
          
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <!-- 設置毫秒單位的阻塞超時 -->
        <property name="connectionProperties" value="oracle.net.READ_TIMEOUT=1000"/>  


        <!-- 其他屬性設置... -->
</bean>

如果同時有多個屬性要設置,在value中通過分號分隔。其他數據庫的設置方式參見資料3。
 
超時捕獲
在Transaction timeout設置生效的情況下,發生超時后,框架將主動回滾當前事務並拋出UncategorizedSQLException。這是一個RuntimeException的子類,通過其getSql()或getMessage()方法可以得知引發超時的sql語句。
在使用JDBC Driver Socket阻塞超設置時,發生超時后,當前連接將被driver關閉,事務中正在執行的操作,不論是通過JdbcTemplate還是其他ORM框架執行的,都將引發SQLException(異常信息為:關閉的連接),這個異常將被上層的TransactionInterceptor捕獲並被重新包裝成一個UncategorizedSQLException的實例,隨后回滾事務,但由於連接已關閉,因此又會引發回滾異常,所以會看到
“TransactionInterceptor.completeTransactionAfterThrowing (TransactionAspectSu pport.java:414)
Application exception overridden by rollback exception ”
最終,會向調用者拋出一個TransactionSystemException的實例,通過其getApplicationException()方法可以獲得被覆蓋前的那個UncategorizedSQLException的實例。
 
參考資料
1. Understanding JDBC Internals & Timeout Configuration
2. Spring transaction timeout doesn't work?
3. Spring事務超時時間可能存在的錯誤認識
4. Using Spring 3 with Mybatis 3 Tutorial – part 1


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM