notes on 'expert oracle'-no.7.1: concurrency-concurrency with multi-version-chenjianjx的专栏-iteye技术网站...

notes on 'expert oracle'-no.7.1: concurrency-concurrency with multi-version-chenjianjx的专栏-iteye技术网站
2011年09月01日
   1. Oracle除了用锁实现并发控制,还利用了“多版本机制”-- 一条数据除了会记在表文件里,还会记在“回滚段”里。
  2. 具体的并发控制策略
  a.ANSI标准定义的并发控制级别(从低到高)
  i.Read Uncommited (可以读到脏数据)
  ii.Read Commited (不能读到脏数据)
  iii.Repeatable Read (在同一个事务里两次读某条数据,读到的值一定是一样的。一个典型的反面例子是“丢失更新”)
  iv.Serializable (不但可以重复读,而且还可以保证没有 幻读)
  b.Oracle支持哪些级别?
  i.Read Uncommited -- 在Oracle中想脏读都读不到!
  ii.Read Commited -- 支持,是Oracle的默认级别。Oralce不仅支持这个级别,而且还有所增强:可以保证 “读一致性”(见下文)
  iii.Repeatable Read -- 不直接支持。需自己编程实现。
  iv.Serializable -- 支持。但是由于未使用锁机制,因此不能真正地实现“串行”
  3. 对各级别的支持的具体实现
  基本原则是: 不用读锁,而是用多版本机制来支持。所谓的多版本,就是某个事务修改某行后,会把该行原来的值放到回滚段(Undo Segment)中,也就是说,除了表文件中的数据版本外,还有一个版本放在回滚段中。
  这里还必须引入一个概念:读一致性(Read Consistency).
  举例来说,帐户A =100元, 帐户B = 100元,现在一个会话把50块钱从账户A转到帐户B,如果另一个会话在读取A和 B时,要么读到 A=100, B=100,或者A=50, B=50,那么这个数据库就支持了读一致性。
  i.Read Uncommited -- N/A
  ii.Read Commited
  A. Oracle如果发现某行数据是脏的(被另一个事务修改,但这个事务还没有提交),就会从回滚段中读出这个版本,即修改前的版本。其它的数据库没有Oracle这么强大,它们只会通过阻塞当前的读操作,直到那个修改事务释放了写锁。
  B. Oracle在这里支持“语句”级别的读一致性。这里必须举例说明。 会话甲从10点整开始读取Sum(A,B),但转账会话乙也正要运行,具体步骤是:
  10:00 会话甲读取A = 100元
  10:05 会话乙插进来把A改成50元,把B改成150元,这时Oracle会在回滚段里设置(10:05, A = 100元,B = 100元);接着会话乙提交事务。
  10:10 会话甲读取B。但它发现B自它读取A时已经发生了变化,于是忽略表文件里的值,而是从会话乙的回滚段里去读本条语句开始后B的值,即10:00以后B的值, 读得10:05时,B= 100元
  所以最后,Sum(A,B) 是 200元,实现了“读一致性”。
  似乎平淡无奇。但如果换了其它的数据库,最后结果会是250元,因为会话甲会把B读成150元。
  iii.Repeatable Read
  A.Oracle不提供直接支持。其它某些数据库可能会支持Repeatable Read ,但它们是通过加读锁来支持的。也就是我在读时你不准改。Oracle认为这样做会严重影响并发能力。
  B.Oracle也可以通过自己加悲观锁来实现。如Select ... for update
  C.当然,通过乐观锁也能实现。
  iv.Serializable
  A.也是通过多版本机制来实现的,不过在这里这个机制扩展到了整个事务级别。举例说明。
  10:00 会话甲用select语句在读取A = 100元
  10:05 会话乙把A改成50元,并提交事务。这时Oracle会在回滚段里设置(10:05, A = 100元)
  10:10 会话再次用select语句读取A的值。它会发现A的值已经被改变了。于是它就从回滚段里读取本事务开始后B的值,也就是10:00以后的值,该值是100元。
  所以,Repeatable Read就实现了。幻读也是用同样的机制实现的。
  B. 此时Oracle还会通过乐观锁机制来防止丢失更新。
  C. Oracle中的Serializable不是真正的串行化。具体的例子可以看原书。
  4. Oralce还支持一种特有的事务级别叫做"Read Only". "Read Only"的隔离性与Serializable一致,但Read Only事务只能有读操作。
  5. 回滚段的问题: 回滚段的大小是有限的。如果你一个事务长达24小时,而又想在事务结束前从回滚段中读取事务开始时的某个数据的值,那你可能读不到东西了,因为你要的数据已经被其它事务覆盖掉了。这时侯你会收到一个异常。
  另一个问题是,从回滚段里读东西也是有一定代价的。在并发程度很高的生产环境里,一个报表查询可能会多次读取回滚段,所以执行速度会稍慢于你的测试环境,因为测试环境的并发通常会低一些。
  
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值