天天看點

spring+jotm+jta+xapool+hibernate+oracle架構中多資料源出現的問題

公司一系統使用了spring+jotm+jta+xapool+hibernate+oracle架構,系統出現了500錯誤,錯誤資訊如下:

java.sql.SQLException: SQLException in StandardPoolDataSource:getConnection
exception: java.sql.SQLException: Cannot get connection for URL jdbc:oracle:thin:@10.4.1.110:1521:testdb
: 調用中無效的參數
	at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:218)
	at org.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:168)
	at org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:133)


……
           

其中資料源配置的部分bean如下(網上找的示例,和我的格式一樣):

<bean id="dataSource_stat" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
  <property name="dataSource">
	   <bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
		  <property name="transactionManager">
				<ref local="jotm"/>
		  </property>
		  <property name="driverName">
				<value>oracle.jdbc.OracleDriver</value>
		  </property>
		  <property name="url">
				<value>jdbc:oracle:thin:@10.4.1.110:1521:testdb</value>
		  </property>
		  <property name="minCon" value="1">
	 </bean>
  </property>
  <property name="user">
		<value>t_wms</value>
  </property>
  <property name="password">
		<value>111</value>
  </property>
 </bean>
 
 <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBea n"/>
 <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransaction Manager">
	<property name="userTransaction"><ref local="jotm"/></property>
 </bean>
           

    錯誤比較奇怪的地方在于:

1.部分子產品出現該錯誤,部分子產品不會出現。
2.出現該錯誤的子產品,有時候會正常,有時候會出現上述錯誤。
3.出現錯誤的子產品中,使用級聯操作的頁面出現的機率高,查詢單獨表的頁面出現錯誤的機率小。
           
1.排查問題的過程中,首先排除了代碼問題,原因是系統部署使用另外擷取資料源的方式,如,把資料源配置在resion中,是不會出現該問題的。
2.懷疑是jar包沖突的問題。在排查過程中,發現資料庫連接配接的jar包之間沒有問題,與資料源配置在resion中系統的lib包中資料連接配接的jar包是一樣的,包括ssh的包。
3.懷疑是xa事務控制的問題。
           

   在調查xapool的問題時,發現也有coder也出現了類似的問題,不過時間比較早。畢竟xapool 1.5版本是2005年釋出的,2006年釋出了1.6beat版本後就沒再更新過。

主要解決方案有

方案1.

   如果是使用的1.5版本的

Oracle9i有名的記憶體溢出bug導緻:Xapool對PreparedStatement進行了Cache,同時Oracle有一個出名的記憶體漏洞,PreparedStatement使用之後必須關閉,如果不關閉連續進行SQL查詢會造成前面SQL的遊标不能釋放;
   Xapool1.5的修改如下:
修改StandardConnectionPoolDataSource類的public static final int DEFAULT_PREPAREDSTMTCACHESIZE = 0,(當然也可以用配置的方式來注入)
這樣就關閉了PreparedStatement的Cache,而且也不會造成什麼1.4中關閉連接配接時的異常等等.
           

    或者:

下載下傳xapool源碼包,然後在org.enhydra.jdbc.pool.GenericPool中,找到life = (Long) unlocked.get(o); 代碼
之後在下面加入:


if (life == null)  continue;  
           

   建議使用1.6版本的吧,畢竟自己需要檢視源代碼和修改,如果不慎可能造成不可預知的後果。

方案2.可以把資料源修改為

<bean id="dataSource_stat" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
	  <property name="transactionManager">
			<ref local="jotm"/>
	  </property>
	  <property name="driverName">
			<value>oracle.jdbc.OracleDriver</value>
	  </property>
	  <property name="url">
			<value>jdbc:oracle:thin:@10.4.1.110:1521:testdb</value>
	  </property>
	  </property>
	  <property name="user">
			<value>t_wms</value>
	  </property>
	  <property name="password">
			<value>111</value>
	  </property>
	  <property name="minCon" value="1">
 </bean>
           

    這個方案是自己測試發現的,可以使用,但是貌似沒有走資料連接配接池。

  方案3.

     資料連接配接池中資料源中都配置使用者名和密碼,即StandardXAPoolDataSource中要配置user和password,StandardXADataSource中也要配置user和password如:

<bean id="dataSourcePool" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">
  <property name="dataSource">
	   <bean id="innerDataSource" class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">
		  <property name="transactionManager">
				<ref local="jotm"/>
		  </property>
		  <property name="driverName">
				<value>oracle.jdbc.OracleDriver</value>
		  </property>
		  <property name="url">
				<value>jdbc:oracle:thin:@10.4.1.110:1521:testdb</value>
		  </property>
		  <property name="user">
				<value>t_wms</value>
		  </property>
		  <property name="password">
		<value>111</value>
  </property>
		  <property name="minCon" value="1">
	 </bean>
  </property>
  <property name="user">
		<value>t_wms</value>
  </property>
  <property name="password">
		<value>111</value>
  </property>
 </bean>
           

  這個問題挺奇怪的,如果有朋友有其他好的解決方案,歡迎交流~~

參考位址:http://www.blogjava.net/hunteva/archive/2009/01/20/62936.html

               http://forum.springsource.org/archive/index.php/t-28145.html

               http://fableking.iteye.com/blog/954153