Oracle-11g中的并发控制(2012/11/16)

1 事务基础

在DB中,可能出现如下3种现象

脏读

在事务中,读到了其它事务没有提交的记录

不可重复读

在事务中,即使查询条件相同,下次返回的记录与上次返回记录不一样,不一样体现在记录被修改或记录被删除

幻影读

在事务中,即使查询条件相同,下次返回的记录与上次返回记录不一样,不一样体现在新增加了记录。

SQL92规定的事务隔离级别如下表。


oracle支持3种事务隔离级别:read-only/readcommitted/serializable。其中read-only不属于SQL92,readcommitted是oracle的默认隔离级别。

2 oracle中并发控制

2.1 多版本并发控制

在undo segment中保留了历史数据,也就是说记录可能有多个版本,版本用SCN(systemchange manage)来识别。SCN是事务提交后系统为之分配的一个全局唯一的事务ID。undo segment中的数据有3种功能:便于事务回滚,提供读一致性,支持flashback。

查询语句被启动的同时获取当前的SCN,DB只会返回SCN小于当前SCN的记录。多版本并发控制技术使得读不阻塞写,写不阻塞读,从而大大的提高了系统的并发性。【多个版本的数据是存储在undo segment中】


2.2 oracle支持的读一致性

oracle支持两个级别的读一致性。语句级读一致性和事务级读一致性。oracle天生支持语句级读一致性,只有隔离级别在serializable时支持事务级读一致性。

●语句级读一致性

读到的数据集和查询启动时的结果集是一样的。也就是说,不存在脏读,也不会读到查询启动之后其它事务提交的数据(包括update/delete/insert)。

●事务级读一致性

概念和serializable是一致的。

2.3 oracle中的锁

2.3.1 上锁的时机以及持续时间

上锁发生在语句级别,解锁发生在事务级别。即提交事务或回滚时释放锁,事务开始时不会获取锁,而是在执行过程中,若语句需要才会上锁。

2.3.2 锁的类型

●DML锁即data锁,保护数据

●DDL锁即dictionary锁,保护对象的定义

●内部锁和latch,保护内部的数据结构,比如数据文件

2.3.3 DML锁

2.3.3.1行锁

当事务需要修改某个记录时,需要获取这个记录对应的行锁。在执行update/delete/insert/select…for udpate时,获取行锁。

实际上,一个行锁可能对应多个记录。即行锁是一个粗粒度的锁,其开销不大,所以系统不会控制单个事务被上锁的记录的数量。

【理解】其实oracle不需要细化到一个记录的锁。比如,T1事务现在需要修改记录R,但是此时记录R已经被事务T2上锁,T1需要等待T2被提交或回滚是才能操作记录R,T2被被提交或回滚涉及到的记录是所有被T2修改过的记录。

2.3.3.2表锁

DDL和DML都需要表锁。在DML操作中需要获取表锁的语句有insert/delete/update/select…forupdate/lock table.

表是由行组成的,当我们向某个表加锁时,一方面需要检查该锁的申请是否与原有的表级锁相容;另一方面,还要检查该锁是否与表中的每一行上的锁相容。比如一个事务要在一个表上加 S 锁,如果表中的一行已被另外的事务加了 X 锁,那么该锁的申请也应被阻塞。如果表中的数据很多,逐行检查锁标志的开销将很大,系统的性能将会受到影响。为了解决这个问题,可以在表级引入新的锁类型来表示其所属行的加锁情况,这就引出了“意向锁”的概念。意向锁的含义是如果对一个结点加意向锁,则说明该结点的下层结点正在被加锁;对任一结点加锁时,必须先对它的上层结点加意向锁。如:对表中的任一行加锁时,必须先对它所在的表加意向锁,然后再对该行加锁。这样一来,事务对表加锁时,就不再需要检查表中每行记录的锁标志位了,系统效率得以大大提高。

 锁有两种基本的锁类型(S锁、X 锁),可以自然地派生出两种意向锁:

意向共享锁(Intent Share Lock,简称 IS 锁):如果要对一个数据库对象加S锁,首先要对其上级结点加IS 锁,表示它的后裔结点拟(意向)加 S锁;

意向排它锁(Intent Exclusive Lock,简称 IX 锁):如果要对一个数据库对象加X 锁,首先要对其上级结点加 IX锁,表示它的后裔结点拟(意向)加X 锁。

另外,基本的锁类型(S、X)与意向锁类型(IS、IX)之间还可以组合出新的锁类型,理论上可以组合出4种,即:S+IS,S+IX,X+IS,X+IX,但稍加分析不难看出,实际上只有 S+IX 有新的意义,其它三种组合都没有使锁的强度得到提高(即:S+IS=S,X+IS=X,X+IX=X,这里的“=”指锁的强度相同)。所谓锁的强度是指对其它锁的排斥程度。

 这样我们又可以引入一种新的锁的类型共享意向排它锁(SharedIntent Exclusive Lock,简称 SIX 锁) :如果对一个数据库对象加 SIX 锁,表示对它加 S 锁,再加IX 锁,即 SIX=S+IX。例如:事务对某个表加 SIX 锁,则表示该事务要读整个表(所以要对该表加S 锁),同时会更新个别行(所以要对该表加 IX

锁)。这样数据库对象上所加的锁类型就可能有5 种:即S、X、IS、IX、SIX。

具有意向锁的多粒度封锁方法中任意事务 T 要对一个数据库对象加锁,必须先对它的上层结点加意向锁。申请封锁时应按自上而下的次序进行;释放封锁时则应按自下而上的次序进行;具有意向锁的多粒度封锁方法提高了系统的并发度,减少了加锁和解锁的开销。

 Oracle的 DML锁(数据锁)正是采用了上面提到的多粒度封锁方法,其行级锁虽然只有一种(即X锁),但其 TM锁(表级锁)类型共有5种,分别称为共享锁(S锁)、排它锁(X 锁)、行级共享锁(RS锁)、行级排它锁(RX 锁)、共享行级排它锁(SRX 锁),与上面提到的S、X、IS、IX、SIX 相对应。

 各个锁的意义如下:【个人理解,有待验证】

RS锁

表示事务要读取表的少量记录

RX锁

表示事务要修改表的少量记录

S锁

表示事务要读取表的绝大部分记录

SRX锁

表示事务要读取表的绝大部分记录

并且需要修改少量记录

X锁

表示事务要修改表的绝大部分记录

或者需要修改表的定义

 各个粒度的锁的相容性如下:



【理解】

进行DML操作只会获取RX粒度的表锁,由于RX之间是相容和的,所以DML之间在表锁层次是不会相互阻塞的。进行DDL操作时获取X锁(个人猜测)。因为读操作不需枷锁,为什么还需要S/RS/SRX粒度的表锁?答案是为用户自己控制并行性提供条件

 2.3.4 DDL锁

用于保护对象的定义,用户不能显示的获得。事务会对其涉及到对象添加DDL锁,从而避免在操作对象数据的过程中对象被删除或定义被修改。DDL锁分为3个类型

Exclusive DDL lock

DDL需要修改对象的定义时需要获取此锁。在这种情况下,DDL也会获取表锁(应该是X锁)。

Shared DDL lock

比如在create procdure过程中需要此锁

Breakable DDL lock

在shared SQL area中,存储了已经解析并优化过的SQL语句,这些SQL语句是和对象(比如table/view)相关联,若关联的对象的定义改变,那么在shared SQL area对应的SQL语句就失效了。

在对象的定义发生变化后,Breakable DDL lock用来通知shared sql area删除对应的SQL项。

 2.3.5 内部锁和latch

latch是轻量级锁。用于保护SGA共享的数据结构。

2.3.10 锁转换和锁提升(Data LockConversion Versus Lock Escalation)

锁转换

改变锁的严格程度,比如把 S锁转换为X锁

锁升级

改变锁的粒度,比如把行锁变为表锁

 因为锁升级大大的提升了死锁的概率,所以oracle从来不会进行锁升级。

2.3.11 死锁

oracle会自动检测死锁,发生死锁后,回滚其中的一个事务的当前语句。应用如何避免死锁?各个事务按照相同的顺序处理数据。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章