(a)基本概念
锁的2种最基本、最简单的类型:排他锁(eXclusive lock,即X锁)、共享锁(Share lock,即S锁)。
不同级别的锁定协议及其作用:
申请的锁
及其作用
锁定协议
修改时申请X锁
读取时申请S锁
作用
操作
结束
释放
结束
释放
操作
结束
释放
事务
结束
释放
不
丢失
修改
不
脏读
可
重复读
一级锁定协议
是
是
二级锁定协议
是
是
是
是
三级锁定协议
是
是
是
是
是
锁定对象的大小被称为锁定的粒度(granularity)。
如果在一个数据库管理系统中,同时支持多种锁定粒度供事务选择,这种锁定方法就被称为多粒度锁定(multiple granularity locking)。
多粒度锁定协议是指,允许对多粒度树中的节点单独地加锁,另外,对一个节点加锁还意味着对这个节点的各级子节点也加同样的锁。因此,可以用两种方法对多粒度树中的节点加锁:显式锁定、隐式锁定。显式锁定是在事务中明确指定要加在节点上的锁;隐式锁定是由于在其上级节点中加显式锁时而使该节点获得的锁。
具有意向锁的多粒度锁定方法能提高系统的并发度,减少加锁和解锁的开销。
意向锁的含义是,如果对一个节点加某种意向锁,则表示对它的所有下级节点加这种锁的意向;如果对一个节点加某种锁,则必须先对该节点的各级上级节点加这种意向锁。
有如下几种意向锁。
一、IS锁(Intended Share lock,意向共享锁)
二、IX锁(Intended eXclusive lock,意向排他锁)
三、SIX锁(Share Intended eXclusive lock,共享意向排他锁)
如果对一个节点加SIX锁,则表示对它加S锁,然后再加IX锁,即SIX=S+IX。例如,如果事务T对表A加SIX锁,则表示事务T要读取整个表(S锁的作用),同时还会更新某些记录(IX锁的作用)。
包括意向锁的各种锁之间的相容规则:(NL表示没有锁定)
T保持的锁
Ti想获取的锁
NL
IS
IX
S SIX X IS 可以 可以 可以 可以 可以 不可以 IX 可以 可以 可以 不可以 不可以 不可以 S 可以 可以 不可以 可以 不可以 不可以 SIX 可以 可以 不可以 不可以 不可以 不可以 X 可以 不可以 不可以 不可以 不可以 不可以死锁是一种比较严重的、特殊的锁争用类型。在这种锁争用中,两个或两个以上的用户正在等待对方锁定的资源。因此,如果不进行某种干预,任意一个事务都无法完成。
诊断死锁方法有:
*超时法。如果一个事务的等待时间超过了规定的时限,就认为发生了死锁。
*等待图法。这是用离散数学的图论来诊断死锁的方法。事务的等待图是一个有向图G=(T,U)。T为正在运行的各个事务的节点的集合,U为有向边。如果T1 事务等待T2事务,则在T1、T2节点之间就有一条从T1指向T2的有向边。DBMS的并发控制子系统周期性地(如每隔1分钟)检测事务等待图。如果发现图中存在回路,则表示系统中出现了死锁。
(b)DDL锁
Oracle主要有2种锁:DDL锁(字典锁)、DML锁(数据锁)。
DDL锁能防止在用DML语句操作数据库表时,对表进行删除,或对表的结构进行更改。
DDL锁由Oracle自动加锁和释放。不能显式地给对象加DDL锁,即没有加DDL锁的语句。
DDL锁的类型与特征:
类型
加锁条件/原因
特征
共享DDL锁
当发布audit、grant、revoke、comment、create procedure、create function、create package等这种DDL语句时
1) 不能防止类似的DDL语句或任何DML语句操作对象,但能防止另一个用户改变或删除已引用的对象
2) 在DDL语句执行期间,该DDL锁一直保持,直到发生一个隐式的提交
排他DDL锁
当发布create table、alter table、drop table、delete from table、truncate table等这种DDL语句时
假如一个用户在表上具有锁,不管它是什么级别、什么类型的锁,另一个用户就不能在该表上加排他DDL锁
可分解的解析锁
(breakable parse lock)
SQL共享池里的语句或PL/SQL对象具有一个用于它所引用的每一个对象的锁 用来保护SQL共享池里的各个语句或PL/SQL对象。假如被引用的对象改变了,该锁能检查语句是否失效。只要语句还在SQL共享池中,该锁就存在
(c)DML锁
根据锁定的粒度和意向,DML锁有几种模式。
RS(Row Share)或SS(Sub Share)
RX(Row eXclusive)或SX(Sub eXclusive)
S(Share)
SRX(Share Row eXclusive)或SSX(Share Sub eXclusive)
X(eXclusive)
可以从%ORACLE_HOME%/RDBMS /ADMIN目录中的dbmslock.sql脚本中找到DML锁的模式的相容规则。
==================
-- These are the various lock modes (nl -> "NuLl", ss -> "Sub Shared",
-- sx -> "Sub eXclusive", s -> "Shared", ssx -> "Shared Sub eXclusive",
-- x -> "eXclusive").
--
-- A sub-share lock can be used on an aggregate object to indicate that
-- share locks are being aquired on sub-parts of the object. Similarly, a
-- sub-exclusive lock can be used on an aggregate object to indicate
-- that exclusive locks are being aquired on sub-parts of the object. A
-- share-sub-exclusive lock indicates that the entire aggregate object
-- has a share lock, but some of the sub-parts may additionally have
-- exclusive locks.
--
-- Lock Compatibility Rules:
-- When another process holds "held", an attempt to get "get" does
-- the following:
--
-- held get-> NL SS SX S SSX X
-- NL SUCC SUCC SUCC SUCC SUCC SUCC
-- SS SUCC SUCC SUCC SUCC SUCC fail
-- SX SUCC SUCC SUCC fail fail fail
-- S SUCC SUCC fail SUCC fail fail
-- SSX SUCC SUCC fail fail fail fail
-- X SUCC fail fail fail fail fail
==================
(d)数据库级别锁定
Oracle可以在数据库、表、行这3个级别上使用锁。
锁定数据库有2种方法:将数据库设置成受限方式、将数据库更改成只读方式。
在shutdown数据库后,通过startup restrict命令来在启动数据库时将其设置成受限方式。也可以通过alter system enable restricted session或alter system disable restricted session语句来在打开数据库的情况下启用或禁用数据库的受限方式。当数据库处于受限方式时,只允许具有 restrictive session系统权限的用户(如sys用户)连接到数据库。已经连接的会话不受alter system enable restricted session语句的影响,只有试图进行连接的新的会话会被限制。
将数据库更改成read only(只读)方式后,只能查询数据而不允许对数据进行任何DML操作。
SQL> STARTUP MOUNT
SQL> ALTER DATABASE OPEN READ ONLY;
如果要将数据库再按读写方式打开,可以用STARTUP FORCE命令重启数据库。
set transaction read only语句可以将事务设置成只读事务,即将数据库"冻结"到该事务开始的那一点上,直至显式地发布了COMMIT或ROLLBACK命令或隐式提交(执行DDL)。在只读事务中所查询到的数据反映的是该事务开始时已经存在的数据库中的数据,即便在此同时其他事务更改并提交了数据库中的数据也是如此,但并不锁定数据库。