ORACLE报“ORA-00054:资源正忙,但指定以 NOWAIT 方式获取资源,或者超时失效”的错误(v$locked_object、v$session、v$lock的使用)
一、错误类型
二、解决异常步骤
1、通常是因为增加或删除数据没有提交,执行一下commit就可以了
2、如果commit还不行,就执行以下命令。
1、SELECT SESSION_ID FROM V$LOCKED_OBJECT; --查看被锁对象的ID 2、SELECT SID,SERIAL#,USERNAME,OSUSER FROM V$SESSION WHERE SID=SESSION_ID; --SESSION_ID是第一步查出来会话ID,查出session会话的sid和serial# 3、ALTER SYSTEM KILL SESSION 'SID,SERIAL#';
--对该会话进行终止.SID会被重用,同一个SID被重用时,SERIAL会增加,不会重复,所以结束会话时要指出SID和SERIAL#
3、通过sql输出结束进程语句
select 'alter system kill session '''||sid||','||serial#||''' immediate;' from v$session where sid in (select blocking_session from v$session) and seconds_in_wait>120
//将锁定时间超过120秒的回话kill掉
三、视图详解
1、v$lock
查看数据库中的锁
select * from v$lock;
--SID:持有锁的会话SID,与v$session相关联
--TYPE:锁的类型。TM表示表锁或DML锁,TX表示行锁或事务锁,UL表示用户锁。
--LMODE:会话保持的锁的模式。0=NONE;1=NULL;2=ROW-S;3=ROW-X;4=SHARE;5=S/ROW-X;6=EXCLUSIVE。
--ID1/ID2:根据TYPE的值而定,主要是TM和TX。TYPE=TM时,ID1=OBJECT_ID,与DBA_OBJECTS相关联,ID2=0
--REQUEST:REQUEST=n,表示该会话正在等待lmode=n的锁
--BLOCK:该会话是否被锁。0=没被锁;1=被锁。
2、v$locked_object
查询数据库中被锁的对象
SELECT * FROM V$LOCKED_OBJECT; --OBJECT_ID:被锁对象ID --SESSION_ID:持有锁的SESSION_ID --ORACLE_USERNAME:持有锁的ORACLE用户名 --OS_USER_NAME:持有锁的系统用户名 --PROCESS:操作系统进程号 --LOCKED_MODE:锁模式
3、v$session
查询数据库中的会话信息
SELECT * FROM V$SESSION; --SADDR:会话地址 --SID:会话ID --SERIAL#:SID会被重用,同一个SID被重用时,SERIAL会增加,不会重复 --PADDR:进程地址,关联V$PROCESS的ADDR字段,关联查出当前session对应操作系统的那个进程的id --USER#:用户名编号 --USERNAME:用户名 --COMMAND:命令类型 --ONERID:所属用户的ID --TADDR:事务地址,关联V$TRANSACTION表的ADDR,关联查出当前session正在使用的回滚段的情况 --LOCKWAIT:等到锁的地址 --STATUS:会话状态 --SERVER:服务器类型。 --PROCESS:操作系统客户机进程ID ....
可以通过v$session查看阻塞会话a的会话b,最后阻塞会话a的会话c(b阻塞a,但是c是最后一个阻塞a),下面是做的一个小实验:
conn hr/hr123; //开启会话1 select * from dept; //在会话1修改DEPARTMENT_ID=100的行数据信息,但未提交 update dept set LOCATION_ID=1800 where DEPARTMENT_ID=100; conn hr/hr123; //开启会话2 update dept set LOCATION_ID=1800 where DEPARTMENT_ID=100; //对同一行进行操作,未能执行成功 //在会话3查询阻塞的会话 conn hr/hr123; select sid,serial#,blocking_session,final_blocking_session from v$session where BLOCKING_SESSION is not null or FINAL_BLOCKING_SESSION is not null;
显示会话33被会话30阻塞了,通过阻塞会话sid查找sql_id,再查看具体的sql语句。
select sql_text from v$sql where sql_id in (select sql_id from v$session where sid=30);
select session_id,sql_id from v$active_session_history; //查看每秒数据库的会话信息
三、参考链接
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示