Jcat
宠辱不惊,闲看庭前花开花落~~
posts - 173,comments - 67,trackbacks - 0

一致和并发是对立的,需要根据应用,选择权宜之计


数据不一致的现象

---事务内单SQL的情况---
1.脏读-Dirty Read:本事务读取了其它事务尚未提交的修改数据
例子:读了不该读的
1:00 x=1
1:01 A用户 Update x=2(但未commit)
1:02 B用户 Select x --> x=2
合理的情况是x仍然等于1

---事务内多SQL的情况(典型的如,先查再改)---
2.不可重复读-Non Repeatable Read
例子1:自相矛盾
1:00 x=1 y=2
1:01 B用户 Select x,y --> x=1 y=2
1:02 A用户 Update x=2; Commit;
1:03 B用户 Select x+y --> x+y=4
首先这个结果从单条SQL的角度看,是没有问题的。但是,如果把B的两次查询看作一个整体(事务),那么合理的情况应该是
  x+y仍然等于3
  或者B再进行一次事务,得出 x=2 y=2 x+y=4 的结果


例子2:更新丢失
1:00 x=1
1:01 B用户 Select x --> x=1
1:02 A用户 Select x --> x=1
1:03 A用户 Update x=2; Commit;
1:04 B用户 Update x=3; Commit;
同样,从单条SQL来讲,没有任何问题。
但是从逻辑的合理性讲,一般的更新操作都是先查再改,换言之
  A真正想做的是Update x from 1 to 2
  B真正想做的是Update x from 1 to 3
但最终却造成了在B不知情的情况下,把B的初衷改为了Update x from 2 to 3


3.幻影读-Phantom Read
例子:读到了未来
1:00 X1=1 X2=2
1:01 B用户 Select Xi --> X1=1 X2=2
1:02 A用户 Insert X3=3; Commit;
1:03 B用户 Select sum(Xi) --> re=6
其实道理和之前的不可重复读相同,只不过是由Insert引起的罢了。
(甚至Delete也会引起类似的问题,但好像学术界并没有对Delete进行讨论)




Isolation Level
Read Uncommitted:1,2,3都会发生
  Oracle中严格禁止脏读
  在SQL Server 7.0中,是可以选择该级别的
Read Committed:发生2,3(Oracle的默认级别)
Repeatable Read:发生3
Serializable:都不发生


Oracle的实现方式
Read Committed:默认就实现
Repeatable Read:
  1. 悲观锁(select ... for update),影响并发
  2. 乐观锁(update where 所有字段都作为条件),不影响并发
Serializable:
  alter session set isolation_level=serializable/read only
posted on 2009-12-05 17:45 Jcat 阅读(209) 评论(0)  编辑  收藏 所属分类: Database

只有注册用户登录后才能发表评论。


网站导航: