Oracle 锁详解(lock)

1 概述

1.1 思维导图

在这里插入图片描述

2 分类

分类(可跳转至 Oracle 官方文档) 描述
v$locked_object 描述 DML 锁信息
dba_ddl_locks 描述 DDL 锁信息
v$lock 当前获取的所有锁信息

2.1 DML 锁 - v$locked_object

概念:

'共享锁[S 锁]',又称为 '读锁',获得 '共享锁' 后,可以查询但无法修改数据
	若事务 T 对数据对象 A 加了 S 锁,则事务 T 可以读 A,但不能修改 A,
    其它事务只能再对 A 加 'S 锁'(而不能加 X 锁),直到 T 释放 A 上的 S 锁
    这保证了其它事务可以 '读 A',但在 T 释放 A 上的 S 锁之前不能对 A 做任何修改
    
'排它锁[X 锁]':又称为 '写锁''独占锁',获得 '排它锁' 后,既可以查询又可以修改数据
	若事务 T 对数据对象 A 加了 X 锁,则事务 T 既可以读 A,又可以修改 A
	其它事务不能再对 A 加'任何锁',直到 T 释放 A 上的锁
	这保证了其它事务在 T 释放 A 上的锁之前 '不能再读取和修改 A'

常用查询:

SELECT lo.session_id 会话id,
       s.serial# 会话序列号,
       p.spid 会话进程号,
       s.username 所属用户,
       s.machine 客户端,
       do.object_name 被锁对象,
       do.object_type 被锁对象类型,
       ceil((SYSDATE - s.logon_time) * 24 * 60 * 60) "被锁时间(S)"
  FROM v$locked_object lo, -- object_id 
       v$session       s, -- saddr {sid }
       v$process       p, -- addr 
       dba_objects     do -- object_id 
 WHERE s.sid = lo.session_id
   AND p.addr = s.paddr
   AND do.object_id = lo.object_id
   AND s.schema# <> 0
-- AND s.username = '';

2.2 DDL 锁 - dba_ddl_locks

SELECT ddl_s.session_id 会话id,
       s.serial# 会话序列号,
       p.spid 会话进程号,
       s.username 所属用户,
       s.machine 客户端,
       do.object_name 被锁对象,
       do.object_type 被锁对象类型,
       ceil((SYSDATE - s.logon_time) * 24 * 60 * 60) "被锁时间(S)"
  FROM dba_ddl_locks ddl_s, -- session_id 
       v$session     s, -- saddr {sid }
       v$process     p, -- addr 
       dba_objects   do -- object_id 
 WHERE s.sid = ddl_s.session_id
   AND p.addr = s.paddr
   AND do.object_id = s.row_wait_obj#
   AND s.schema# <> 0
-- AND s.username = '';

2.3 所有锁 - v$lock

SELECT l.sid         "会话ID",
       s.serial#     "会话序列号",
       p.spid        "会话进程号",
       l.type        "锁类型",
       s.username    "所属用户",
       s.machine     "客户端",
       o.object_name "被锁对象",
       o.object_type "被锁对象类型",
       l.ctime       "被锁时间(S)"
  FROM v$lock      l, -- addr
       v$session   s, -- saddr 
       dba_objects o, -- object_id 
       v$process   p -- addr 
 WHERE s.sid = l.sid
   AND o.object_id = l.id1
   AND p.addr = s.paddr
   AND l.type IN ('TM', 'TX')  -- 我们只需要关注 TM / TX 锁即可
-- AND s.username = ''
;

3 示例

3.1 DML 锁明细

  • 此部分了解即可。
  • 以下给出各语法,若有兴趣,请自行尝试
CREATE TABLE scott.test(
   ID   NUMBER,
   NAME VARCHAR2(30)
);

INSERT INTO scott.test(id, name) values(1, 'a');
COMMIT;
锁模式 锁描述 全称 解释
0 none lock requested but not yet obtained 已请求锁,但未获得
1 null select 查询
2 rows_s(ss) row share lock 行级共享锁
3 row_x(sx) row exclusive table lock 行排它表锁
4 share(s) share table lock 共享表锁
5 s/row-s(ssx) share row exclusive table lock 共享行独占表锁
6 exclusive(x) exclusive table lock 排它表锁

“锁模式” 值越大,所影响的行数越多!

详细的解释可以参考 Oracle 官方文档 v$locked_object 中的 locked mode 链接(Oracle Database Concepts …)

0 - none - 已请求锁,但未获得

session 1:

lock table scott.test in share mode nowait;

session 2:

update scott.test t set t.name = 'aa' where t.id = 1;

测试截图:
在这里插入图片描述

1 - null - select

2 - rows_s(ss) - row share lock

语法:(以下同理,不在赘叙)

lock table <表名>[, <表名>] in row share mode [nowait]
lock table <表名>[, <表名>] in share update mode [nowait];

nowait:被锁的语句会 '一直等待' 上一个获得锁的语句 '释放锁'
        指定 nowait,可以不用进行等待,直接反馈 'ORA-00054: 资源正忙 

示例:

lock table scott.test in row share mode nowait;

lock table scott.test in share update mode nowait;

测试截图:
在这里插入图片描述

3 - row_x(sx) - row exclusive table lock

select * from scott.test for update;

insert into scott.test(id, name) values(2, 'b');

update scott.test t set t.name = 'aa' where t.id = 1;

delete from scott.test t where t.id = 1;

测试截图:

在这里插入图片描述

4 - share(s) - share table lock

示例:

lock table scott.test in share mode nowait;

测试截图:
在这里插入图片描述

5- s/row-s(ssx) - share row exclusive table lock

示例:

lock table scott.test in share row exclusive mode nowait;

测试结果:
在这里插入图片描述

6 - exclusive(x) - exclusive table lock

示例:

lock table scott.test in exclusive mode nowait;

测试截图:
在这里插入图片描述

3.2 for update skip locked

日常中,我们常用的锁语句有如下:
insert
update
delete
select ... for update

解锁语句如下:
commit
rollback

扩展:

猜你喜欢

转载自blog.csdn.net/qq_34745941/article/details/106939087