ORACLE的TX锁和TM锁及解锁

本文介绍了Oracle数据库中TX锁和TM锁的概念,重点讲述了如何在不知道锁定情况时进行解锁操作。通过查询v$session视图可以查看数据库的锁定状态,找出被锁定的会话以及阻塞其他会话的‘罪魁祸首’。通常,提交或回滚事务即可自动解锁,但在特定情况下,可以通过执行`ALTER SYSTEM KILL SESSION`来强制结束锁定会话。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库是一个并发访问的系统,所以说对一个数据库来说最大的问题就是并发控制的问题,这个并发控制所表现的不是在并发读上面,而是在并发写上面。对应并发写,就需要保证数据的一致性!那么什么是是数据一致性呢? 先看看什么是数据的不一致性。

数据不一致性:
脏读
张三的存款是1000,早上10点某个做了一个update 变成10000 update xxx set money=10000 where xx 但是没有提交,10点过1分的时候张三去查发现他的钱变成了10000了,这个就是脏读,因为张三读取的是没有提交的数据


不可重复读取:
张三 700
。。。
。。。
李四 1000

在10点的时候有一个人发出了一个select * from t;的sql 先读取了张三700的这个记录, 10点过1分查询还在进行,这个时候有个用户做了一个转账,把从李四的卡里面转了300给张三,当用户读取到李四这个记录的时候,如果返回的结果是700,那么就是一个不可重复读

幻影读
10点发起了一个全表扫描,10点过1分的时候查询还在进行,然后在10点过2分insert了一条记录为vic,那么查询到这个记录的时候是否会读取,如果读取了那就是是一个幻影读


维护这几种数据库一致性oracle都是通过undo的方式去实现的





一致性的另外一个情况,如果说有两个用户同时想修改表中的一行怎么办??

测试:

锁的特点:
自动管理
伴随整个事物


锁的种类:
1、DML锁
在对数据进行修改的时候就会产生DML锁,一个事务会产生两把锁,一个是行级别的TX锁,一个是表级别的表级共享锁

为什么要有TX和TM的存在呢?
select sid,TYPE,ID1,ID2,LMODE,REQUEST,CTIME from v$lock; --发起dml,使用语句查询

TX(行级别)
保护事务中某一行的一致性

TM(表级别)
尝试drop table;

2、DDL锁


3、LATCH

队列机制,先进先出,一个个的排队


DML锁

TX锁:


通过一个具体的sql,去理解DML锁

用户发出 update emp set sal=100 where empno=7369;

1、找到empno=7369这行的位置,比如说在100号块上面
2、分配undo数据块,并且把7369这个人原来的sal的值放入到undo上面
3、在数据块上分配一个ITI槽,记录事务id,undo的地址,scn,状态(是否提交)等信息
4、找到empno=7369这行的记录,在行头设定锁标记,记录当前事务的iti号
5、把控制全交给用户



在第四步 行头的时候就是一个TX锁。
问题:
如果需要跟新的不是一行记录呢??where deptno=10?? 会有几个TX锁?
因为这三条记录是属于同一个事物的的,tx是叫事物排它锁。

测试:
SQL> update emp set sal=100 where empno=7369; --有几个TX锁、几个TM锁

1 row updated.

SQL>
SQL>
SQL>
SQL> update emp set sal=10 where deptno=30; --有几个TX锁、几个TM锁

6 rows updated.

SQL>
SQL> update dept set loc='GZ' where deptno=10;--有几个TX锁、几个TM锁

1 row updated.



v$lock
ADDR 锁对象的地址
KADDR
SID
TYPE 锁类型
ID1 锁标示
ID2 锁标示
LMODE 锁模式 下面会将到
REQUEST 要求得到什么样的锁模式,0表示不要求
CTIME
BLOCK

一个个的介绍这里面的字段
TX锁、TM锁中ID1,ID2的含义
为TM锁时候,ID1表示被锁定的对象的OBJECT_ID,ID2此时为“0”。
TX锁的时候 ID1对应视图V$TRANSACTION中的XIDUSN字段(Undo segment number:事务对应的撤销段序列号)和XIDSLOT字段(Slot number:事务对应的槽位号)。其中ID1的高16位为XIDUSN,低16位为XIDSLOT。

查看高16位对应的值:
select trunc(131076/power(2,16)) XIDUSN from dual;
查看低16位对应的值:
select bitand(131076,to_number('ffff','xxxx'))+0 XIDSLOT from dual;

16为这个东西。。。 不用管




v$transaction
每一个事务在v$transaction里面有个记录

XIDUSN:就是事务的回滚段号
XIDSLOT:就是ITL列表中,slot的号
XIDSQN:就是表示这个slot被重复使用的次数


对lock来说,使用的是先到先得的机制,会有一个锁队列去控制
测试:
session 1 update dept set loc='GZ' where deptno=10;
session 2 update dept set loc='BJ' where deptno=10;
session 3 update dept set loc='SZ' where deptno=10;

select sid,TYPE,ID1,ID2,LMODE,REQUEST,CTIME from v$lock where type in ('TM','TX');

当session 1释放锁的时候,session2 和session 3谁先会获取到锁资源??



TM 锁




锁模式   锁描述   解释  SQL操作
0   none
1   NULL   空   Select
2   SS(Row-S)   行级共享锁,其他对象只能查询这些数据行   、Lock for update、Lock row share
3   SX(Row-X)   行级排它锁,在提交前不允许做DML操作   Insert、Update、Delete、Lock row share
4   S(Share)   共享锁   Create index、Lock share
5   SSX(S/Row-X)   共享行级排它锁   Lock share row exclusive
6   X(Exclusive)   排它锁   Alter table、Drop table、Drop index、Truncate table 、Lock exclusive



alter table t move;

insert into t values xxxx;


手工锁定表:没有理由不要这样做
LOCK TABLE emp in ROW SHARE mode;
LOCK TABLE emp in ROW EXCLUSIVE mode;
LOCK TABLE emp in SHARE mode;
LOCK TABLE emp in SHARE ROW EXCLUSIVE mode;
LOCK TABLE emp in EXCLUSIVE mode;

可以用这个测试一下其它的锁冲突


========================================
DDL锁
在DDL语句时产生的锁
排他DDL锁
drop table
alter table

share DDL锁
create procure 里面有很多对象,会在对应的对象上加一个共享的DDL锁,共享锁的目的是为了防止别人获得排他性的锁


死锁:
session 1
update scott.emp set sal=1 where empno=7369;

session 2
update scott.emp set sal=1 where empno=7499;

这个时候session 1 想更新7499
session 1
update scott.emp set sal=1 where empno=7499; --被hang住,啥都动不了
如果session2再去update 7369呢?
session 2
update scott.emp set sal=1 where empno=7369; --理论上也会被hang住,7369被session1获取,要等session1,但是session1要更新7499,由于被session2阻塞,啥都动不了,session2去等一个啥都动不了的session 结果就是永远等待,oracle发现这个问题会自动打破这个死锁

=============================================

解锁

解锁最简单的就是在进行了增删改查的用户进行commit或rollback就可以了提交事物就自动解锁,但是在不知道谁的情况下又是如何解锁了;

select sid,serial#,event from v$session where event like '%TX%'; --查看数据库的情况
select sid,serial#,event,blockint_session from v$session where event like '%TX%'; --看谁被锁了
select sid,serial#,username,machine,blocking_session from v$session where sid=1; 查看罪灰祸手
alter system kill session '1,18'; 根据查出来的sid 和serial# 能确定是谁了然后kill 掉


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Knuuy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值