首页 > 编程知识 正文

C#中使用TransactionScope类(分布式事务) 和 锁

时间:2023-05-06 04:25:00 阅读:215499 作者:4250

如果在C#中使用TransactionScope类(分布式事务),则须注意如下事项:
1、在项目中引用using System.Transactions命名空间(先要在添加net组件的引用);

2、具体示例如下:

public static void sendMessage() { TransactionOptions transactionOption = new TransactionOptions(); //设置事务隔离级别 transactionOption.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted; // 设置事务超时时间为60秒 transactionOption.Timeout = new TimeSpan(0, 0, 60); using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOption)) { try { //TODO scope.Complete(); } catch (Exception ex) { throw new Exception(ex.Message); }finally{ //释放资源 scope.Dispose(); } } } namespace System.Transactions{ // // Summary: // Specifies the isolation level of a transaction. public enum IsolationLevel { // // Summary: // Volatile data can be read but not modified, and no new data can be added during the transaction.可读取但不可修改易失性数据,并且在此过程中不能添加新数据交易。 Serializable = 0, // // Summary: // Volatile data can be read but not modified during the transaction. New data can be added during the transaction.在事务期间可以读取但不能修改易失性数据。新数据可以在事务处理期间添加。 RepeatableRead = 1, // // Summary: // Volatile data cannot be read during the transaction, but can be modified.事务期间无法读取易失性数据,但可以对其进行修改。 ReadCommitted = 2, // // Summary: // Volatile data can be read and modified during the transaction.在事务期间可以读取和修改易失性数据。 ReadUncommitted = 3, // // Summary: // Volatile data can be read. Before a transaction modifies data, it verifies if // another transaction has changed the data after it was initially read. If the // data has been updated, an error is raised. This allows a transaction to get to // the previously committed value of the data.可以读取易失性数据。在事务修改数据之前,它会验证另一个事务在最初读取数据后更改了数据。如果数据已更新,出现错误。这使得事务可以到达以前提交的数据值。 Snapshot = 4, // // Summary: // The pending changes from more highly isolated transactions cannot be overwritten.无法覆盖来自高度隔离事务的挂起更改。 Chaos = 5, // // Summary: // A different isolation level than the one specified is being used, but the level cannot be determined. An exception is thrown if this value is set.正在使用与指定隔离级别不同的隔离级别,但无法确定。如果设置了此值,则会引发异常。 Unspecified = 6 }}

事务五种隔离级别IsolationLevel属性一共支持五种事务设置,具体介绍如下:
(1)DEFAULT
  使用数据库设置的隔离级别(默认),由DBA 默认的设置来决定隔离级别。
(2)READ_UNCOMMITTED
  这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。
  会出现脏读、不可重复读、幻读 (隔离级别最低,并发性能高)。
(3)READ_COMMITTED
  保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。
  可以避免脏读,但会出现不可重复读、幻读问题(锁定正在读取的行)。
(4)REPEATABLE_READ
  可以防止脏读、不可重复读,但会出幻读(锁定所读取的所有行)。
(5)SERIALIZABLE
  这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。
  保证所有的情况不会发生(锁表)。

3、对MSDTC组件设置:
     在控制面板--->管理工具--->服务 中,开启Distributed Transaction Coordinator 服务。
     a.控制面板->管理工具->组件服务->计算机->我的电脑->右键->属性
     b.选择MSDTC页, 确认"使用本地协调器"
     c.点击下方"安全配置"按钮
     d.勾选: "允许网络DTC访问","允许远程客户端","允许入站","允许出站","不要求进行身份验证".
     e.对于数据库服务器端, 可选择"要求对呼叫方验证"
     f.勾选:"启用事务Internet协议(TIP)事务"。
     g.在双方防火墙中增加MSDTC.exe例外
     可用命令行: netsh firewall set allowedprogram %windir%system32msdtc.exe MSDTC enable

4、重启IIS服务器。

2 锁

锁有乐观锁和悲观锁

2.1乐观锁实现方法有两种

2.1.1加入时间戳

2.1.2 在UPDATE数据前对数据进行比对

Set @money=Select money from account where accountId=1Update account set money =2000 where accountId=1 and money=@money

这就实现了一个最简单的乐观锁,在update之前对拿到的数据进行判断或者加入时间搓机制

2.2 悲观锁

在事务一开始就对你后面要修改的记录锁定

Select * from account with (UPDLOCK) where accountId=1

一但锁住,accountId=1 这一个记录 在此事务结束前,别人都无法对其进行修改或读取,要等待此事务结束。

使用悲观锁,千万不要用以下语句

Select top 1 * from account with (UPDLOCK)

这样会锁住account整个表,其他事务都无法对此表进行读取或者修改

在并发量不大的时候可以使用悲观锁,一但我要修改某条记录,我就锁住它,直到我整个事务完成。

并发量比较大的还是要使用乐观锁,但是要有失败处理机制。

参考

  TransactionScop事务机制的使用

  脏读、不可重复读 共享锁、悲观锁 和 事务五种隔离级别

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。