文章目录
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 …)
session 1:
lock table scott.test in share mode nowait;
session 2:
update scott.test t set t.name = 'aa' where t.id = 1;
测试截图:
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
扩展: