当前位置: 首页 > news >正文

oracle 锁的添加方式和死锁的解决

DML锁添加方式
DML 锁可由一个用户进程以显式的方式加锁,也可通过某些 SQL 语句隐含方式实现。
DML 锁有三种加锁方式:共享锁方式、独占锁方式、共享更新。
共享锁,独占锁用于 TM 锁,共享锁用于 TX 锁。
1)共享方式的表级锁
共享方式的表级锁是对表中的所有数据进行加锁,该锁用于保护查询数据的一致性,防止其它用户对已加锁的表进行更新。其它用户只能对该表再施加共享方式的锁,而不能再对该表施加独占方式的锁,共享更新锁可以再施加,但不允许持有共享更新封锁的进程做更新。
共享该表的所有用户只能查询表中的数据,但不能更新。
共享方式的表级锁只能由用户用 SQL 语句来设置,语句格式如下:
LOCK TABLE <表名>[,<表名>]… IN SHARE MODE [NOWAIT]
执行该语句,对一个或多个表施加共享方式的表封锁。当指定了选择项NOWAIT,若该锁暂时不能施加成功,则返回并由用户决定是进行等待,还是去执行别的语句。持有共享锁的事务,在出现如下之一的条件时,便释放其共享锁:
执行 COMMIT 或 ROLLBACK 语句。
退出数据库( LOG OFF)。
程序停止运行。
共享方式表级锁常用于一致性查询过程,即在查询数据期间表中的数据不发生改变。
2)独占方式表级锁
独占方式表级锁是用于加锁表中的所有数据,拥有该独占方式表封锁的用户,即可以查询该表,又可以更新该表,其它的用户不能再对该表施加任何加锁(包括共享、独占或共享更新封锁)。其它用户虽然不能更新该表,但可以查询该表。
独占方式的表加锁,格式如下:
LOCK TABLE <表名>[,<表名>]… IN EXCLUSIVE MODE [NOWAIT]
独占方式的表级锁也可以在用户执行 DML 语句 INSERT、UPDATE、DELETE时隐含获得。独占方式封锁通常用于更新数据,当某个更新事务涉及多个表时,可减少发生死锁.
3)共享更新加锁方式
共享更新加锁是对一个表的一行或多行进行加锁,因而也称作行级加锁。表级加锁虽然保证了数据的一致性,但却减弱了操作数据的并行性。
行级加锁确保在用户取得被更新的行到该行进行更新这段时间内不被其它用户所修改。因而行级锁即可保证数据的一致性又能提高数据操作的迸发性。
获得行级锁,格式如下:
LOCK TABLE < 表 名 >[,< 表 名 >]… IN SHARE UPDATE MODE
[NOWAIT]

10.3DDL锁
在DDL操作中会自动为对象加DDL锁,从而保护这些对象不会被其他会话锁修改。例如,如果执行了一个 alter table 操作,表上就会加一个排他DDL锁,这个排他DDL锁会防止其他会话得到这个表上的DDL锁和TM锁。
DDL 锁又可以分为:排它 DDL 锁、共享 DDL 锁、分析锁。
排它 DDL 锁:创建、修改、删除一个数据库对象的 DDL 语句获得操作对象的排它锁。如使用 alter table 语句时,为了维护数据的完成性、一致性、合法性,该事务获得一排它 DDL 锁。
共享 DDL 锁:需在数据库对象之间建立相互依赖关系的 DDL 语句通常需共享获得 DDL 锁。如创建一个包,该包中的过程与函数引用了不同的数据库表,当编译此包时该事务就获得了引用表的共享 DDL 锁。
分析锁:Oracle 使用共享池存储分析与优化过的 SQL 语句及 PL/SQL 程序,使运行相同语句的应用速度更快。一个在共享池中缓存的对象获得它所引用数据库对象的分析锁。
分析锁是一种独特的 DDL 锁类型, Oracle 使用它追踪共享池对象及它所引用数据库对象之间的依赖关系。当一个事务修改或删除了共享池持有分析锁的数据库对象时, Oracle 使共享池中的对象作废,下次在引用这条 SQL/PLSQL 语句时, Oracle 重新分析编译此语句。
DDL 级加锁是由 Oracle RDBMS 来控制,它用于保护数据字典和数据定义改变时的一致性和完整性。它是系统在对 SQL 定义语句作语法分析时自动地加锁,无需用户干予。
字典/语法分析加锁共分三类:
(1)字典操作锁: 用于对字典操作时,锁住数据字典,此封锁是独占的,从而保护任何一个时刻仅能对一个字典操作。
(2) 字典定义锁: 用于防止在进行字典操作时又进行语法分析,这样可以避免在查询字典的同时改动某个表的结构。
(3)表定义锁: 用于一个 SQL 语句正当访问某个表时,防止字典中与该表有关的项目被修改。
10.4死锁的产生和解决
当两个用户希望持有对方的资源时就会发生死锁。即两个用户互相等待对方释放资源时,Oracle认定为产生了死锁,在这种情况下,将以牺牲一个用户作为代价,另一个用户继续执行,牺牲的用户的事务将回滚。造成死锁的原因就是多个线程或进程对同一个资源的争抢或相互依赖。
Oracle 的死锁问题实际上很少见,如果发生,基本上都是不正确的程序设计造成的,经过调整后,基本上都会避免死锁的发生。
在 Oracle 系统中能自动发现死锁,并选择代价最小的,即完成工作量最少的事务予以撤消,释放该事务所拥有的全部锁,使其它的事务继续工作下去。
从系统性能上考虑,应该尽可能减少资源竞争,增大吞吐量,因此用户在给并发操作加锁时,应注意以下几点:
(1)对于 UPDATE 和 DELETE 操作,只锁定要做改动的行,在完成修改后立即提交。
(2)当多个事务正利用共享更新的方式进行更新,则不要使用共享封锁,而应采用共享更新锁,这样其它用户就能使用行级锁,以增加并行性。
(3)尽可能将对一个表的操作的并发事务施加共享更新锁,从而可提高并行性。
(4)在应用负荷较高的期间,不宜对基础数据结构(表、索引、簇和视图)进行修改
如果死锁不能自动释放,就需要手工杀死会话。
【例10-1】建立测试表testLock,然后插入测试记录,并在该表上添加行级锁后不提交事物。删除表中一条记录后产生死锁,查看死锁并杀掉死锁会话。
具体代码如下:
– 第十章\sisuo.sql

–建立测试表
CREATE TABLE testLock(
ID NUMBER,
test VARCHAR(100)
);

-插入数据
INSERT INTO testLock VALUES(1,‘test1’);

INSERT INTO testLock VALUES(2,‘test2’);

COMMIT;

SELECT * FROM testLock ;

–加行级锁 并对内容进行修改,不提交

SELECT * FROM testLock FOR UPDATE;

查询是否产生死锁,代码如下:
Select s.username,l.object_id,l.session_id,s.serial#, s.lockwait,s.status,s.machine,s.program
from v s e s s i o n s , v session s,v sessionsvlocked_object l where s.sid = l.session_id;
执行后发现没有死锁。
字段说明:
Username:死锁语句所用的数据库用户.
SID: session identifier,session 标示符,session 是通信双方从开始通信到通信结束期间的一个上下文。
SERIAL#: sid 会重用,但是同一个sid被重用时,serial#会增加,不会重复。
Lockwait:可以通过这个字段查询出当前正在等待的锁的相关信息。
Status:用来判断session状态。Active:正执行SQL语句。Inactive:等待操作。Killed:被标注为删除。
Machine: 死锁语句所在的机器。
Program: 产生死锁的语句主要来自哪个应用程序。
另外打开一个SQL窗口,删除数据代码如下:
delete from testLock WHERE ID=1;
执行后发现不能执行,一直处于等待状态,如图所示10-2所示。
在这里插入图片描述

图10-2删除数据处于等待状态

查询是否产生死锁,代码如下:
select s.username,l.object_id, l.session_id,s.serial#, s.lockwait,s.status,s.machine,s.program
from v s e s s i o n s , v session s,v sessionsvlocked_object l where s.sid = l.session_id;
执行后如图10-3所示。
在这里插入图片描述

图10-3查询死锁
查询产生死锁的语句,代码如下:
select sql_text from v s q l w h e r e h a s h v a l u e i n ( s e l e c t s q l h a s h v a l u e f r o m v sql where hash_value in (select sql_hash_value from v sqlwherehashvaluein(selectsqlhashvaluefromvsession
where sid in (select session_id from v$locked_object));
执行该语句后,结果如图10-4所示。
在这里插入图片描述

图10-4查询死锁语句

死锁的处理,取v l o c k e d o b j e c t 视图中 s e s s i o n i d ,取 v locked_object视图中session_id,取v lockedobject视图中sessionid,取vsession视图中serial#字段的值,然后杀掉会话,代码如下:
alter system kill session ‘9,87’;

再查看一下死锁,会发现已经没有stauts为active的记录了,发生死锁的语句已经被终

相关文章:

  • Yocto meta-toradex-security layer 创建独立数据分区
  • MongoDB副本集搭建与核心机制
  • 【回眸】香橙派Zero2(全志H616)初探
  • 2026届华为海思秋暑期IC实习秋招笔试真题(2025.04.23更新)
  • 函数的多种参数使用形式
  • 驱动开发系列53 - 一个OpenGL应用程序是如何调用到驱动厂商GL库的
  • 基于Python爬虫的音乐歌手的歌名和歌词信息爬取(可以输入歌手名字,然后爬取到该歌手的全部歌名和歌词信息)
  • Ubuntu主机上通过WiFi转有线为其他设备提供网络连接
  • 【蓝桥杯】产值调整
  • 基于大模型的结肠癌全病程预测与诊疗方案研究
  • Android插拔U盘导致黑屏问题排查
  • macOS 连接远程服务器的推荐方法和工具
  • Kingbase性能优化浅谈
  • 《深入理解计算机系统》阅读笔记之第一章 计算机系统漫游
  • SVN 右键不显示clean up的解决方法
  • java—11 Redis
  • vxe-table封装表头
  • 10天学会嵌入式技术之51单片机-day-7
  • LLM应用开发(八)-聊天机器人有记忆功能
  • 自然语言处理(NLP)技术的实例
  • 从息屏24小时到息屏1小时,姚明在深圳开启落地试点
  • 央行副行长:上海国际金融中心建设是我国参与国际金融竞争的核心载体
  • 福建一改造项目1人高处坠亡且事故迟报41天,住建厅约谈相关责任单位
  • 高明士︱纪念坚苦卓绝的王寿南先生
  • 开发国内首个泌尿专科智能体,医生们将临床经验转变为知识图谱
  • 助力中国足球未来,香港赛马会鼎力支持U15国少选拔队赴英训练