分布式事务(四)——事务隔离

潜在的事务隔离问题

在事务中可能存在的潜在问题可以被归纳为这三类:脏读(Dirty reads)、非可重复性读取(Nonrepeatable reads)和幻读(Phantoms)。

●   脏读——脏读的意思是你可以从一个事务外部读取事务内部被改变的数据。假设事务一改变了一些客户信息,但是这个事务失败了,所以在回滚后数据并没有改变。如果同时事务二也在读取这些客户记录,则读取出来的数据实际上并不存在,这就是脏读。

●   非可重复性读取——如果同一行的数被读取多次,你每次得到的值都不相同,则被称为非可重复性读取。比如你在事务一内读取数据,而与此同时事务二改变了你在事务一中读取的那些数据,然后你在事务一中再次读取了该数据,这样同一个事务内多次读取相同数据的值却不同。这就是非可重复性读取。

●   幻读——幻读的意思是某个记录满足搜索条件,但没有出现在查询结果内。比如你在事务一内按照某种查询条件查询数据,而与此同时事务二插入了一条新的记录,并且此记录也能满足事务一中的查询条件,则这条记录行就属于幻读。譬如所有满足事务一内查询的纪录都被更新了(譬如,所有薪水小于$1000的雇员的薪水都被调整到$1000),在事务一结束后,在事务二新添加的这条记录未被更新。

Transaction Isolation Levels
事务隔离级别

取决于设定的隔离级别,这些问题中有些可能会发生,或者隔离级别保证了这些问题都不会发生。你可以为隔离级别设定这些值:可读取未提交数据(read uncommitted)、

可读取提交数据(read committed)、可重复读取(repeatable read)和序列化(serializable)。

●   可读取未提交数据——如果配置为这个级别,事务并没有互相隔离开来。对于事务来讲这是最有扩缩性的的方式,但是前面提到的所有问题都有可能发生。

●   可读取提交数据——在这个级别,事务必须等待所有在它操作范围内那些带有写入锁的记录解锁。这样就保证了脏读的情况不会发生。事务对所有的只读行持有一个读取锁,对所有更新或者删除的行持有一个写入锁。在移动到下一行后读取锁会被解开,而所有的写入锁都将被维持直到事务被完成或者中止为止。

●   可重复性读取——可重复性读取在原理上和可读取提交数据相似。唯一的不同处在于,读取锁会一直被保持到事务被完成或中止为止。这样,非可重复性读取的问题将不存在。

●   序列化——与可读取提交数据和可重复性读取类似,事务必须等待所有在它操作范围内那些带有写入锁的记录解锁。与可重复性读取类似,读取锁一直作用于只读的行上,写入锁一直作用于更新或者删除的行上,区别在于被锁定数据的范围。如果执行查询语句SELECT * FROM Customers,则表Customers会被锁定。这样没有新的纪录可以被插入。如果查询语句是SELECT * FROM Customers WHERE City = ‘Vienna’,则所有City列值为Vienna的行都被锁定了。这样,幻读行不可能出现。表7-5总结了各个隔离级别下可能发生的问题。

When to Use Which Isolation Level
什么时候使用什么隔离级别

一致性和并发能力是相互冲突的。为了保持数据的一致性,在访问数据时必须加锁。为了最严格的一致性,序列化级隔离提供了最好的支持。而锁定数据同样意味着别的作业无法同时访问该数据。为了得到更好的并发操作的能力,你得选择一个低一点的隔离级别。

表7-5  隔离级别行为

事务隔离级别行为
隔离级别可读取未提交数据可读取提交数据可重复性读取序列化
脏读YesNoNoNo
非可重复性读取YesYesNoNo
幻读YesYesYesNo
 

根据具体要做的事情,你可以选择一个合适的隔离级别。如果仅仅是要插入一些新的记录,那你可以设置隔离级别为读取未提交数据。如果数据会被读取一次或多次,并且如果不要求严格保持一致性(比如你正在建立一个管理报告),你可以设置为可读取提交数据。

考虑如何配置隔离级别时,需要先考虑整个保护的任务在任务进行中会发生什么事情,这些事情会怎样影响到任务的执行。有了这些信息,你可以选择出需要的隔离级别。

Specifying the Isolation Level
指定隔离级别
通过给[Transaction]特性的Isolation属性赋一个TransactionIsolationLevel枚举值,你可以设定一个服务组件的事务隔离级别。

 

[Transaction(TransactionOption.Required,

   Isolation = TransactionIsolationLevel.Any)]

[EventTrackingEnabled]

public class CustomerData : ServicedComponent

 

表7-6展示了TransactionIsolationLevel各个枚举值和其含义。

表7-6  TransactionIsolationLevel枚举

TransactionIsolationLevel值

描述

Any

如果你设置隔离级别为Any,则使用和调用者相同的隔离级别。如果该对象已经是根对象,则使用的隔离级别是Serializable。

ReadUncommitted

使用ReadUncommitted时,仅使用共享锁,独占锁不会被允准。假如你只是需要读取一些数据结果,但是不需要这些数据同步到以秒为计的量级(与数据库完全同步),你应该使用这个选项。

ReadCommitted

使用这个选项,当数据在被读取时使用了共享锁。读完数据后,这个共享锁就会被释放。在事务完成之前,数据可以被改变。

RepeatableRead

如果设置为RepeatableRead,则所有被使用的数据上都会被加上锁。

Serializable

序列级有着最好的隔离效果。在这个选项的作用下,更新或插入在相同范围的数据是被禁止的。

 

如果使用无组件事务,你可以通过设定ServiceConfig类的Isolation属性来指定需要的事务隔离级别。
 
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

honkerhero

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值