锁的简介:

Oracle实现并发访问控制,通过锁来实现。

锁分为悲观锁(事务调度可能会串行调度)--事务级别的行级锁。

乐观锁(事务被串行调度)-- 时间戳和基于验证的事务调度。

所谓乐观锁是指事务调度串行机制不会打乱,保证每个事务之间数据更改彼此不会受影响,维护数据一致性。

Oracle默认隐式执行锁定机制,采用影响行数最少的行级锁,在数据库块中存储锁定行的信息。

锁针对某个事务的整个过程,在发出commit或rollback后锁自动消失。

锁的锁定方法:

Oracle采用行级粒度的方式来进行锁定对象,一个事务操作影响几条数据就锁定几行。

粒度越小,支持的并发越大。

锁类型:

锁的对象可以是用户级的表、索引等,也可是共享数据结构(数据字典)。

DML锁

针对保护用户的表和索引,在事务操作的行上加了一把独占行级锁,防止相同数据行同时被多个事务同时更改,在一事务未提交前,后一事务只能等待直到前一事务提交。

在DML锁的同时会持有一个DDL表锁,在DML(insert,update,delete)操作时另一事务不能对表进行定义表结构操作。同一事务可以操作,等待时间取决于操作ddl_lock_timeout

此参数默认值为0

show parameter ddl_;

NAME TYPE VALUE
------------------------------------ ----------- ------
ddl_lock_timeout integer 0



可以在session级别设定等待事件

alter session set ddl_lock_timeout = 30;

-- 设定同一事务ddl锁等待dml锁的时间为30秒,默认为不等待立即执行。

操作等待时间超过设定值直接失效。前提是dml操作时间很长,超过了ddl等待时间。

DDL锁

在DML锁时有附带对应表的DDL锁

闩用于保护sga中共享数据结构,控制对内存结构的访问。

数据字典锁

字典对象被修改时的对应的锁

分布锁

在RAC结构或分布式系统中使用的锁

内部锁

Oracle为保护访问数据文件、表空间、回滚段而使用的锁


锁管理:

在实际应用系统中,会出现进程等待现象,这是阻塞锁导致,有人俗称‘死锁’这是错误的。

死锁 是两个进程彼此等待,造成的死循环。阻塞锁是一个进程等待另外一个进程,当前一进程提交或回滚后,后一进程就能得到对应对象的控制权。

死锁有Oracle内部处理,杀死后请求事务,无需人为参与

阻塞锁

当一个事务在某个对象上的锁阻止或阻塞了其他事务访问相同对象时,阻塞锁就会出现。

在视图 dba_blocks中可查询当前被阻塞的会话ID

select * from dba_blockers;

HOLDING_SESSION
---------------
39

也可在v$session视图中查询当前阻塞的会话

select t.SID,t.USERNAME,t.BLOCKING_SESSION_STATUS,t.BLOCKING_SESSION from v$session t
where t.BLOCKING_SESSION_STATUS = 'VALID';

SID USERNAME BLOCKING_SE BLOCKING_SESSION
---------- ------------------------------ ----------- ----------------
42 halee VALID 39


死锁

两个事务同时对相同对象持有行级独占锁,彼此阻塞就会形成死锁。Oracle自动杀死对改对象锁的后持有者

管理视图

dba_blockers -- 记录当期库中阻塞其他进程的进程

dba_waiters -- 记录等待进程,被阻塞进程,锁类型,即将请求的锁类型

select * from dba_waiters;
WAITING_SESSION HOLDING_SESSION LOCK_TYPE MODE_HELD MODE_REQUESTED LOCK_ID1 LOCK_ID2
--------------- --------------- --------- --------- ---------- ------- ------
42 39 Transaction Exclusive Exclusive 39214 2964

dba_locks -- 记录每个会话具体的锁类型

生成库中锁的情况

执行安装目录下的utllockt.sql文件,可以生成对应锁等待的具体情况

WAITING_SESSION LOCK_TYPE MODE_REQUESTED MODE_HELD LOCK_ID1 LOCK_ID2
----------------- ----------------- --------------- --------------- ----------------- -----------------
39 None
42 Transaction Exclusive Exclusive 393241 2964

返回结果说明:
会话42在等待会话39提交或回滚来回去行独占锁

可采用如下sql 查询对应锁对应的操作

SELECT /*+ ORDERED */sql_text
FROM v$sqltext a
WHERE (a.hash_value, a.address) IN (
SELECT DECODE (sql_hash_value,
0, prev_hash_value,
sql_hash_value
),
DECODE (sql_hash_value, 0, prev_sql_addr, sql_address)
FROM v$session b,dba_blockers c
WHERE b.SID = c.holding_session);