Oracle中的锁概述

原文地址:Oracle中的锁概述 作者:digdeep126

1. Oracle锁的类型:
1)latch: 保护memory structure,典型的就是内存中的chain/list等结构;
2)lock: 保护database object,比如表、索引等等。分为排它锁(X); 共享锁(S)

2. 行级锁:DML语句修改行时,对该行产生行级锁;
   同时, DML语句所在的事务,产生一个事务锁TX;
   同时,行级锁会对所在表产生一个TM(Table Manager) 表级锁RX(Row exclusive);
TM: 即Table Manager,表级锁的总称。
TX: 即Transaction exclusive,事务锁,每一个事务对应一个事务锁。可能对应多个表级的RX锁。
RX: 即Row exclusive,行级排它锁, 是一种TM锁,由行级锁产生在表级别上的锁。因为如果DML语句仅仅只有行级锁,在表上没有锁,会存在问题,比如当一个session在表A上进行DML语句,另一个session来drop表A,这种情况下导致问题。 所以DML语句也需要在表级别上加上一个RX锁,防止表被另一个session删除掉了

3. 表级锁
1)行级排他锁(Row exclusive) RX锁
   当我们进行DML时,会自动在被更新的表上添加RX锁,可以执行LOCK命令显式的在表上添加RX锁
   允许其他事务通过DML语句修改相同表里的其他数据行
   允许使用lock命令对表添加RX锁定
   不允许其他事务对表添加X锁
   行级共享锁(Row Shared,简称 RS锁
select … from for update
   共享锁(Share,简称S锁)
通过lock table in share mode命令添加该S锁
   排他锁(Exclusive,简称 X锁
通过lock table in exclusive mode命令添加X锁
   共享行级排他锁(Share Row Exclusive,简称 SRX锁
       通过lock table in share row exclusive mode命令添加SRX锁
   lock table  in [row share][row exclusive][share][share row exclusive][exclusive] mode;
表级锁,我们一般只关注 RX 和 RS 以及 X锁, RX由DML语句产生,RS由select for update产生,而X锁一般有DDL语句产生
另一个重要的锁是S锁:由create index语句引起。一个问题是: create index在表上加的S锁,和DML语句的RX锁是不兼容的!!!因为显然我们在进行DML操作时,是不能建立索引的。所以create index语句的运行会阻塞表上的所有DML语句。在高负载的系统上应该慎重的运行create index语句。

4. 锁的兼容性:
加锁语句
可见:
select语句没有锁,不会排斥任何其它锁;
DML语句在表上产生RX锁;
select for update在表上产生RS锁;
RS和RS之间,RX和RX之间,以及RS和RX之间都是兼容;
RS和RX在与S和SRX的兼容性上有一些区别。
          
5. 锁相关的视图
1)v$lock
记录了session已经获得的锁定以及正在请求的锁定的信息
SID说明session的ID号
TYPE说明锁定锁定级别,主要关注TX和TM
LMODE说明已经获得的锁定的模式,以数字编码表示
REQUEST说明正在请求的锁定的模式,以数字编码表示
BLOCK说明是否阻止了其他用户获得锁定,大于0说明是,等于0说明否

开始一个事务:
SQL> delete from test_index where object_id=2;
1 row deleted.

SQL> select xidusn,xidslot,xidsqn,status from v$transaction;
    XIDUSN    XIDSLOT     XIDSQN STATUS
---------- ---------- ---------- ----------------
         5         25        545 ACTIVE

事务产生的锁:
SQL> select sid from v$mystat where rownum=1;
       SID
----------
       123
SQL> select sid,type,id1,id2,
decode( lmode,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') lock_mode,
  decode( request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive')
request_mode,block
from v$lock where sid=123;

       SID TY        ID1        ID2 LOCK_MODE           REQUEST_MODE             BLOCK
---------- -- ---------- ---------- ------------------- ------------------- ----------
       123 TM      52516          0 Row Exclusive       None                         0
       123 TX     327705         545 Exclusive           None                         0

结果显示:该session 123产生了两个锁:一个事务锁TX,一个表级锁TM,TM由DML语句产生。
ID1:表示TM锁的对象的object_id:
SQL> select object_name from dba_objects where object_id=52516;
OBJECT_NAME
-----------
TEST_INDEX
LOCK_MODE:表示锁的模式;
REQUEST_MODE:表示是请求其它模式的锁;
BLOCK:是否阻塞了其它的事务;

对于TM锁来说,ID1表示被锁定的对象的对象ID,ID2始终为0
对于TX锁来说,ID1表示事务使用的回滚段编号以及在事务表中对应的记录编号,ID2表示该记录编号被重用的次数

将TX锁的ID1拆解:
SQL> select trunc(327705/power(2,16)) as undo_blk#,bitand(327705,to_number('ffff','xxxx')) + 0 as slot# from dual;
 UNDO_BLK#      SLOT#
---------- ----------
          5         25

这个结果与select xidusn,xidslot,xidsqn,status from v$transaction;的结果是一致的。

2)v$enqueue_lock
查询v$enqueue_lock来获得锁定队列中的session信息
查询出哪些session在申请锁:
select sid,type,decode(request,0,'None',1,'Null',2,'Row share',3,'Row Exclusive',4,'Share',5,'Share Row Exclusive',6,'Exclusive') request_mode from v$enqueue_lock
where sid in(131,153);

3)v$locked_object
记录了当前已经被锁定的对象的信息。

6. 系统允许的事务数量和TM锁的数量:
可以获得的TX锁定的总个数由初始化参数transactions决定,而可以获得的TM锁定的个数则由初始化参数dml_locks决定
SQL> select name,value from v$parameter where name in('transactions','dml_locks');
NAME         VALUE
------------ ------------
dml_locks    748
transactions 187

SQL> select resource_name as "R_N",current_utilization as "C_U",max_utilization as "M_U",initial_allocation as "I_U" from v$resource_limit where resource_name in('transactions','dml_locks');

R_N                                   C_U        M_U I_U
------------------------------ ---------- ---------- --------------------
dml_locks                               1         50        748
transactions                            1         20        187

7. 死锁
在Oracle数据库中,造成死锁的那个DML语句会被撤销。死锁总是由于应用程序设计不合理引起的。
当某个session的事务引起了死锁时,Oracle会自动将阻塞该事务的其他事务中相应的DML语句撤销,而阻塞该事务的其他事务中的其他DML语句并没有撤销。
死锁产生示例:
session 1
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'a' where employee_id=100

session 2
select sid from v$mystat where rownum=1;
update employees set last_name=last_name||'b' where employee_id=101;

session 1
update employees set last_name=last_name||'c' where employee_id=101;

session 2
update employees set last_name=last_name||'d' where employee_id=100;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值