跨数据库(SQL、Oracle)分布式事务

转载 2012年03月29日 13:56:24

KB-.NET 2.0 分散式交易新利器---TransactionScope

古老的ASP時代,要做Distributed Transaction(分散式交易,指跨越異質資料庫的交易,例如: 將SQL Server跟Oracle的更新動作包成一個Transaction),有個偷懶的方法。在ASP最前端宣告一下<%@ Transaction=Required%>,則整個ASP中的所有資料庫操作,不管Oracle、SQL、Sybase,通通會自動包成Transaction,不用多寫半行Code。

不過,這種寧可錯殺一百,不可錯放一個的做法效能有點鳥(連沒必要的SELECT動作也被包入Transaction)。會寫VB COM的人多半會寫顆Support Transaction的COM+元件,用來執行特定的資料庫的更新。而多顆異質資料庫的Transactional元件可以再包出一個大Transaction。不過,這得另外寫COM,註冊到COM+ Application中,多了些額外手續。

ASP.NET 1.x誕生後,針對分散式交易,提供了一個四不像的做法:
寫一顆繼承自System.EnterpriseService.ServicedComponent的元件,內含更新資料庫的程式邏輯,再設定TransactionAttribute,然後要Strong-Named/Signed,包上COM+的皮,註冊放入COM+ Application中。

呃... 好像比以前寫COM+還麻煩,堂堂的.NET還是得回頭靠COM+才能實踐分散式交易,會不會有點...

終於.NET 2.0中,針對分散式交易做出了改良。System.Transactions.TransactionScope讓大家有機會重回ASP時代的美妙時光,可以將任意一段資料庫操作包成一個Transaction,不需要額外的手工。例如以下的範例: (要Oracle支援Transaction,記得安裝Oracle Service For Microsoft Transaction Server,不然會百忙一場。)

   21 TransactionOptions options =new TransactionOptions();

   22 options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;

   23 options.Timeout = new TimeSpan(0, 2, 0);

   24 using (TransactionScope scope =new TransactionScope(TransactionScopeOption.Required, options))

   25 {

   26     try

   27     {

   28         using (SqlConnection sqlCn = new SqlConnection("Data Source=(local); User Id=scott; Password=tigger; Initial Catalog=Lab"))

   29         {

   30             SqlCommand cmd = new SqlCommand("INSERT INTO tblAccount (Account, Password, Username) VALUES (@acct, @pwd, @name)", sqlCn);

   31             cmd.Parameters.Add("@acct",SqlDbType.NVarChar).Value = "EMP" + DateTime.Now.ToString("HHmmss");

   32             cmd.Parameters.Add("@pwd",SqlDbType.NVarChar).Value = "PWD";

   33             cmd.Parameters.Add("@name",SqlDbType.NVarChar).Value = "NAME" + DateTime.Now.ToString("HHmmss");

   34             sqlCn.Open();

   35             cmd.ExecuteNonQuery();

   36         }

   37         //** 實測結果,ODP.NET 9207不Support TransactionScope,必須用.NET 2.0的System.Data.OracleClient

   38         using (OracleConnection oraCn = new OracleConnection("Data Source=MYORA; User Id=scott; Password=tigger;"))

   39         {

   40             OracleCommand cmd = new OracleCommand("INSERT INTO MYTABLE.tblAccount (Account, Password, Username) VALUES (:acct, :pwd, :name)", oraCn);

   41             cmd.Parameters.Add(":acct",OracleType.VarChar).Value = "EMP" + DateTime.Now.ToString("HHmmss");

   42             cmd.Parameters.Add(":pwd",OracleType.VarChar).Value = "PWD";

   43             cmd.Parameters.Add(":name",OracleType.VarChar).Value = "NAME" + DateTime.Now.ToString("HHmmss");

   44             oraCn.Open();

   45             cmd.ExecuteNonQuery();

   46         }

   47         //在scope.Complete();後才算Commit!

   48         scope.Complete();

   49     }

   50     catch (Exception ex)

   51     {

   52         //只要沒有scope.Complete(),先前的動作都會Rollback

   53         Response.Write(ex.Message);

   54     }

   55 }

很簡短吧? (有寫過ServicedComponent的人才能感受出它的好呀!!) 為了證實Transaction效果,我在48行設Breakpoint,則中斷未scope.Complete前,SQL的tblAccount會被鎖定無法SELECT,而ORACLE中則SELECT不到新增的資料(可見SQL用的是Lock大法,ORACLE專攻Snapshot);scope.Complete後,二者的新資料就都出現了。

同時,我還試了故意ORACLE新增動作失敗或不做scope.Complete(),則SQL的tblAccount的新增資料就不會出現。由此,可以驗證以上的程式的確實踐了分散式交易!! 而TransactionScope的確比.NET 1.x的ServicedComponent方便多了,大幅減少異質資料庫包成交易的複雜度。

我曾試著用ODP.NET 9207取代System.Data.OracleClient,測試結果顯示ODP.NET 9207無法參與TrasactionScope物件所建立的交易。後來找到Oracle的ODP.NET FAQ,提到了從ODP.NET 10.2.0.2.20起才支援.NET 2.0的System.Transactions,想用ODP.NET的人要留意。

最後還有一點要注意,如果你的SQL在遠端主機上,用的又是Windows 2003平台,則還有好幾個關節要打通。包含了MSDTC在Windows 2003 SP1上有些選項要調整。還有,你可能會連線失敗,並得到以下這類訊息:
Communication with the underlying transaction manager has failed.
The transaction has already been implicitly or explicitly committed or aborted.

經驗中多半是防火牆的傑作,我的私房解法是在Windows Firewall上開放MSDTC.EXE程式的所有對外連線,問題就可解決。微軟有篇專題文章,介紹MSDTC與Firewall間的愛恨情仇,有興趣的人也可以去挖挖寶。


原帖:http://blog.darkthread.net/blogs/darkthreadtw/archive/2006/11/23/kb-net-2-0-transactionscope.aspx

相关文章推荐

提高Sql Server数据库分布式事务速度性能的经验总结

本文描述如何提高sql server分布式事务速度,减少阻塞的一些经验总结
  • gatr
  • gatr
  • 2016-11-17 15:07
  • 1968

HBase分布式事务与SQL实现

  • 2016-02-22 13:46
  • 616KB
  • 下载

详解Mysql分布式事务XA(跨数据库事务)

在开发中,为了降低单点压力,通常会根据业务情况进行分表分库,将表分布在不同的库中(库可能分布在不同的机器上)。在这种场景下,事务的提交会变得相对复杂,因为多个节点(库)的存在,可能存在部分节点提交失败...

linq to sql 分布式事务

  • 2011-04-02 19:51
  • 623KB
  • 下载

sql server分布式事务解决方案

适用环境操作系统:windows 2003数据库:sql server 2000/sql server 2005使用链接服务器进行远程数据库访问的情况一、  问题现象在执行分布式事务时,在sql se...
  • zbwmx
  • zbwmx
  • 2011-02-17 11:09
  • 552

WCF 使用 WSAtomicTransaction11 分布式事务 Oracle

在WCF 的通信中 使用 WSAtomicTransaction11 来管理Oracle的分布式事务

Spring+Mybatis+Tomat多数据源(mysql+sql server)与atomikos分布式事务配置

最近刚刚转行java开发。入职第一天,要实现将数据保存到mysql和sql server数据库中,并保证事务性,各种查阅资料,以下是完成成果,记录一下: 首先是jar包引入: 关于Atomikos...

SQL Server 2008的分布式事务管理原理

分布式事务跨越两个或多个称为资源管理器的服务器。称为事务管理器的服务器组件必须在资源管理器之间协调事务管理。如果分布式事务由 Microsoft 分布式事务处理协调器 (MS DTC) 之类的事务管理...

JBoss+Oracle+JTA配置分布式事务

首先讲一下我的配置:    JBoss是JBoss-4.2.2.GA    Oracle是Oracle10g (1)(假如我的JBoss装在D盘)把JBoss路径中(D:/jboss-4.2.2.GA...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)