您的位置:首页 > 数据库

数据库并发控制和隔离级别

2014-04-25 23:58 183 查看
数据库的并发操作带来数据的不一致性有 丢失修改,不可重复读,读脏数据。其中不可重复读有三种情况。另外两种为:1 事务T1按照一定条件读取了某些数据,T2删除了部分记录,T1再次按相同条件读取记录时,发现有数据莫名消失。2 事务T1按照一定条件读取了某些数据,T2插入了符合T1条件的数据,T1再次按照相同条件读数据时,发现莫名多出数据。这两种情况叫做幻影读。

T1

T2

T1

T2

T1

T2

read A=1

A=A+1

Write A

read A=1

A=A+1

Write A

read A

read B

C=A+B=2

read A

read B

C=A+B=3

read A

A=A+1

Write A

read A=1

A=A+1

Write A

rollback

read A=2

a丢失修改

b不可重复读

c读脏数据

所以需要封锁技术控制并发操作

锁类型:

X锁,写锁, 排他锁 ,exclusive locks用于数据写操作前进行锁定。 如果事务T对数据A加上X锁,就只允许事务T读取和修改数据A,其他事务不能对数据A再加任何锁,但可以读。直到事务T释放A上的锁才能

S锁,读锁, 共享锁 ,share locks 用于数据读操作前进行锁定。 如果事务T对数据A加上了S锁,事务T就只能读取数据A但不可以修改,其他事务可以再对数据A加S锁执行读取操作,只要数据A上有S锁,任何事物都只能对其加S锁而不能加X锁修改。

封锁粒度和意向锁这里就不讨论了。

锁的持续时间:

在基于锁的并发控制中,隔离级别决定了锁的持有时间。"C"-表示锁会持续到事务提交。 "S" –表示锁持续到当前语句执行完毕。如果锁在语句执行完毕就释放则另外一个事务就可以在这个事务提交前修改锁定的数据,从而造成混乱。

隔离级别

写操作

读操作

范围操作 (...where...)

未授权读

S

S

S

授权读

C

S

S

可重复读

C

C

S

可序列化

C

C

C

由这两种锁组合形成的四种隔离级别也有叫封锁协议

一级封锁协议--未授权读取(Read Uncommitted)

事务T在修改数据A之前必须先对其加X锁,直到事务结束才释放X锁

假设A和B初始都为1

T1

T2

T1

T2

T1

T2

Xlock A

A=A+1

Write A

commit

Unlock A

等待

等待

等待

等待

Xlock A

A=A+1

Write A

commit

Unlock A

read A

read B

C=A+B=2

read A

read B

C=A+B=3

Xlock A

A=A+1

Write A

commit

Unlock A

Xlock A

A=A+1

Write A

rollback

Unlock A

read A=2

a正确

b不可重复读

c读脏数据

其中c读脏数据是这样理解的, 事件T1对A加了排他锁,对数据A进行了修改,若事件T2对A申请锁,则会wait;若事件T2不对A申请任何锁,则即使A加对A加了排他锁,T2也会无视。

二级封锁协议--授权读取(Read Committed)

一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后方可释放S锁

T1

T2

T1

T2

T1

T2

Xlock A

A=A+1

Write A

commit

Unlock A

等待

等待

等待

等待

Xlock A

A=A+1

Write A

commit

Unlock A

Slock A

Slock B

read A

read B

C=A+B=2

Unlock A

Unlock B

等待

等待

Slock A

Slock B

read A

read B

C=A+B=3

Unlock A

Unlock B

等待

等待

等待

Xlock A

A=A+1

Write A

commit

Unlock A

Xlock A

A=A+1

Write A

rollback

Unlock A

等待

等待

等待

·

·

·

·

Slock A

read A

Unlock A

a正确

b不可重复读

c正确

三级封锁协议--可重复读取(Repeatable Read)

一级封锁协议加上事务T在读取数据A之前必须先对其加S锁,直到事务结束才释放。

T1

T2

T1

T2

T1

T2

Xlock A

A=A+1

Write A

commit

Unlock A

等待

等待

等待

等待

Xlock A

A=A+1

Write A

commit

Unlock A

Slock A

Slock B

read A

read B

C=A+B=2

Slock A

Slock B

read A

read B

C=A+B=3

Unlock A

Unlock B

等待

等待

等待

Xlock A

A=A+1

Write A

commit

Unlock A

Xlock A

A=A+1

Write A

rollback

Unlock A

等待

等待

等待

·

·

·

·

Slock A

read A

Unlock A

a正确

b T1读操作是正确的

但是T1范围读是会出现幻影读的

c正确

三级锁的在使用范围条件的时候会发生幻影读

T1

T2

select count[id] from user where id>10

Slock id [id>10]

count[id]=0

commit

Unlock

select count[id] from user where id>10

Slock id [id>10]

count[id]=0

commit

Unlock

insert into user values [id=11]

commit

幻影读

两段封锁协议--序列化(Serializable)

对任何数据进行读写之前,必须对该数据加锁包括使用where的范围读。在释放一个封锁之后,事务不再申请和获得任何锁,只能继续释放锁,直到事务结束。

T1

T2

T1

T2

T1

T2

Xlock A

A=A+1

Write A

commit

Unlock A

等待

等待

等待

等待

Xlock A

A=A+1

Write A

commit

Unlock A

Slock A

Slock B

read A

read B

C=A+B=2

read A

read B

C=A+B=3

Unlock A

Unlock B

等待

等待

等待

Xlock A

A=A+1

Write A

commit

Unlock A

Xlock A

A=A+1

Write A

rollback

Unlock A

等待

等待

等待

·

·

·

·

Slock A

read A

Unlock A

a正确

b正确--不带范围的操作

c正确

两段锁在使用范围操作的时候不会发生幻影读

T1

T2

select count[id] from user where id>10

Slock id [id>10]

count[id]=0

select count[id] from user where id>10

count[id]=1

commit

Unlock

等待

等待

等待

等待

等待

等待

insert into user values [id=11]

commit

正确

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: