分散式事務和資料來源配置

fczhaoxuehui發表於2006-12-12
【主題】透過修改Jboss資料來源配置保證I2SS 中事務操作完整性
【關鍵詞】JTA, UserTransaction, xa-datasource,localtx-datasource
【分類】資料庫 / 編碼實現
【提供者】趙學慧 系統設計部
【問題描述】
場景描述:
在EA 公共管理系統中進行刪除使用者操作。使用技術框架I2SS ,應用伺服器Jboss4.0.2,資料庫 MySql 。
具體問題:
EA 公共管理系統刪除使用者時涉及的操作非常之多,如果刪除失敗,發現出現事務不能回滾,雖然在程式碼中已經進行了事務操作的控制。
【原因分析及解決方法】
透過對Mysql日誌進行分析,發現在一次使用者刪除操作中並不是單純的使用單個資料庫連線來完成。透過進一步的跟蹤發現,在I2SS中每一次呼叫資料庫操作的方法總會試圖獲取一個新的connection。而且還有一個嚴重的問題就是我們的程式中利用UserTransaction 對事務進行控制(注 此API 僅用於控制JTA事務),而我們的資料來源配置確是<local-tx-datasource>。如果利用JTA控制事務,而資料來源是本地事務資料來源的,兩者搭配的情況是事務不會起作用,這就意味著從 JDBC 連線池接收連線時,會從該池將 AutoCommit 設定為 true。這就預示我們的JTA事務控制根本就不起作用。這也就解釋了為什麼使用者刪除事務操作失敗的原因。
為了支援I2SS框架,目前的解決方式就是替換支援分散式事務的驅動,修改資料來源配置將其替換成<xa-datasource>。配置檔案如下:
<datasources>
<xa-datasource>
<jndi-name>DataSource</jndi-name>
<track-connection-by-tx>true</track-connection-by-tx>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
<new-connection-sql>set autocommit=1</new-connection-sql>
<no-tx-separate-pools>true</no-tx-separate-pools>
<xa-datasource-property name="Url">jdbc:mysql://127.0.0.1:3306/sms1?autoReconnect=true</xa-datasource-property>
<xa-datasource-property name="User">smsdb</xa-datasource-property>
<xa-datasource-property name="Password">smsdb</xa-datasource-property>

<transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>

<exception-sorter-class-name>
org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
</exception-sorter-class-name>
<type-mapping>mySQL</type-mapping>

<!--pooling parameters-->
<min-pool-size>5</min-pool-size>
<max-pool-size>100</max-pool-size>
<blocking-timeout-millis>5000</blocking-timeout-millis>
<idle-timeout-minutes>15</idle-timeout-minutes>
</xa-datasource>
</datasources>
在上述配置檔案中使用者色標記出的元素需要特別注意,而且這四個配置元素必須同時使用。下面將進行詳細解釋:
1、<no-tx-separate-pools>
這個元素的設定使得兩個連線池能夠分開:一個支援JTA事務的連線,另一個不支援JTA事務的連線。連線池在第一次使用時建立。
2、<track-connection-by-tx>
當這個值設定為true時,連線管理器會保持一個XID-to-connection影射表,當事務結束時而且所有的連線關閉或者未被引用時連線將放回連線池。這樣做的副作用是不會掛起或者恢復連線的XAResource裡的XID,這個行為和本地事務是一樣的。
3、<xa-datasource-class>
指定javax.sql.XASDataSource實現類的全名
4、<new-connection-sql>
當新的連線建立時執行此語句。
在我們的配置檔案中,我們進行了如下配置:
<new-connection-sql> set autocommit=1</new-connection-sql>
這樣做的原因是因為我們透過MySQLXADataSource中獲取的連線預設被設定成autocommit 為false,如果我們的連線併入到事務中時(即事務啟動之後獲取的連線),會統一由UserTransaction 進行提交。對於那些沒有併入事務中的單連線,就會出現操作一直不能提交的錯誤,可能出現XAER_OUTSIDE 異常。透過上述的設定,我們可以將單連線操作放入一個隔離的連線池中,並將其設定為自動提交。
【避免此類問題的建議】
產生這個問題的原因可以歸結為I2SS框架中事務處理不當,connection 封裝不合理。為了適應框架改用分散式事務,理論上講會造成非常大的效能開銷。

相關文章