数据库的隔离级别   Leave a comment

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


数据不一致的现象

—事务内单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 2009年12月8日 by gw8310 in 未分类

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: