Oracle锁是Oracle在多个事务中防止破坏性访问相同资源的机制,Oracle自动维护必要的锁类型,在应用级别最少限制的情形下提供了最大的并发和数据完整性。同时,通过Oracle的Lock service,也允许用户手动的来维护相应的锁类型。 整体上来说,Oracle提供了两种锁模式(Lock Mode),即互斥模式(exclusive Lock Mode)和共享模式(share lock mode),互斥模式用来修改数据,阻止相关资源被共享,只有一个事务 拥有互斥锁独占相关资源,直到该互斥锁被释放。共享模式允许被访问的资源在多个事务之间共享。 在Oracle机制中中,支持Lock Conversion不支持Lock Escalation,Lock Conversion翻译过来即锁类型转换,比如一个事务中使用SELECT...FOR UPDATE语句,该事务立即在数据行上获得 exclusive的row lcoks并且在表级别获得一个row share table lock,如果该事务之后修改了数据,表级别的row share table lock会自动转换成一个row exclusive table lock.有些数据库 支持Lock escalation,lock escalation即锁的范围扩大化,比如一个事务用很多的行锁来锁定了一个表中很大数量的数据行,数据库会自动将很多个行级锁扩大为一个 表级别的锁。因为lock escalation增大了产生死锁的可能性,所以Oracle不支持。 死锁(Deadlock):通俗地来讲,死锁是指两个事务互斥的锁定了对方等待的资源,A deadlock can occur when two or more users are waiting for data locked by each other.Oracle自动检测 并排除死锁,当死锁发生时Oracle产生ORA-00060d的错误并回滚调其中一个事务,以下是产生死锁的一个例子: Transaction T1 Timestamp Transaction T2
UPDATE t UPDATE t SET t.c1=c1*1.1 t1 SET t.c3=c3*1.2 WHERE t.c2=1 WHERE t.c2=2
UPDATE t UPDATE t SET t.c1=c1*1.1 t2 SET t.c3=c3*1.2 WHERE t.c2=2 WHERE t.c2=1 在时间点t1没有任何问题,但是在t2产生了死锁,因为在T1在t1时间点在c2=1的行上申请了行级锁,T2在时间点t1在c2=2的行上申请了行级锁,而在t2的时间点上T1在c2=2上申请 行级锁,而T2在c2=1上申请行级锁,所以产生死锁现象。 在应用设计级别避免死锁,应该在事务中有序的访问相同的资源,比如多个事务中更新一个master table和一个detail table,我们应该确保在每个事务中都先访问master table, 然后访问detail table,或者相反,这样就能有效的避免死锁的发生。 下面还是直奔主题的来介绍Oracle中的锁类型,Oracle中的锁分DML 锁、DDL锁和内部锁及latch三大类: DML locks (data locks) DML locks protect data. For example, table locks lock entire tables, row locks lock selected rows. DDL locks (dictionary locks) DDL locks protect the structure of schema objects—for example, the definitions of tables and views. Internal locks and latches Internal locks and latches protect internal database structures such as datafiles. Internal locks and latches are entirely automatic. DML锁:在行级别,也叫TX锁或者事务锁,只有exclusive一种模式,也即在行级别,只有互斥锁,在表级别锁上,又叫表级锁或者TM锁,分为RS、RX、S、SRX和X 五种mode. Row Locks(TX):当在INSERT、UPDAET、DELETE和SELECT FOR UPDATE语句中,自动在每个锁定的行上获得TX锁。同时,如果一个事务在一个表上获得 一个行级锁,他总是同时在表级别会获得一个表级锁来保护数据结构。 TM锁:表级锁用来保护表结构,比如防止在DML过程中drop表等。在INSERT、UPDATE、DELETE、SELECT...FOR UPDATE语句下事务会获得TM锁。TM锁模式限制级别从低到高有 RS、RX、S、SRX、X五种类型。以下是SQl语句和对应的表级锁的模式对应关系: SQL statement Mode of Table Lock
select from table none insert into table RX update table RX delete from table RX select from table for update of RS lock table in row share mode RS lock table in row exclusive mode RX lock tablein share mode S lock table in share row exclusive mode SRX lock table in exclusive mode X 另外,这里还有所谓的锁兼容性的问题,比如一个RX类型的表级别锁上面,允许其他事务修改、删除其他行的数据,所以允许其他事务在该表上获得 RX类型的表级别锁,但是不允许X类型的表级锁,关于锁兼容性的问题具体可以查看Oracle相关文档,不再赘述。 DDL locks,DDL lock 用来保护schema下对象的定义,比如在编译一个procedure的过程中,在该过程中引用导的对象会自动获得DDL锁保护,以防止在创建或 编译过程中引用的对象被修改或删除。Oracle DDL锁分为exclusive DDL locks,share DDL locks和breakable parse locks. Exclusive DDL locks:大多数的DDL操作都会获得exclusive DDL locks来保护对象,比如不允许会话一在alter table的过程中会话二drop table等等。 Share DDL locks:一些DDL操作获得share DDL lock用来防止DDL冲突,但是允许多个会话并发的的进行该类型的DDL操作。比如一个会话在Create procedure的过程中, 在该过程中应用到的所偶对象上会获得share DDL lock,其他会话也可以通过create procedure来访问会话一引用到的对象,但是不允许任何一个事务修改引用到的对象。 在下列语句中,会获得share DDL lock:AUDIT, NOAUDIT, COMMENT, CREATE [OR REPLACE] VIEW/ PROCEDURE/PACKAGE/PACKAGE BODY/FUNCTION/ TRIGGER, CREATE SYNONYM, and CREATE TABLE (when the CLUSTER parameter is not included). Breakable Parse Locks:SQL 语句在shared pool中在parse阶段对相应对象加breakable parse locks,以防止在parse阶段相应的对象被修改或删除,但是由于在parse阶段 你依然可以修改或删除相关的对象,所以叫做breakable parse locks.A parse lock is acquired during the parse phase of SQL statement execution and held as long as the shared SQL area for that statement remains in the shared pool.
Latches and Internal Locks:Latches和内部锁用来保护数据库内部对象和内存中的对象,用户不可操作。Latches用来保护SGA中的共享数据结构,比如当前访问数据库的用户 列表和buffer cache中的块。一个服务器或后台进程在操作这些对象的短暂过程中在访问的过程中获得相应的latch. Internal Locks是比latch级别更高更复杂的内部锁类型,包括 Dictionary Cache Locks、File and Log Management Locks、Tablespace and Rollback Segment Locks等,具体参见Oracle 相关文档。
上面对Oracle的锁机制做了基础性的介绍,总之,Oracle锁分DDL和DML锁,DML锁在行级别只有X一种模式,在表级别有RS、RX、S、SRX和X五种模式,常用的数据字典包括v$lock和v$locked_object, 要更深入了解Oracle的锁机制,参考相关文档,请持续关注我的博客关于Oracle Data Concurrency and Consistency的介绍。