Oracle报错:ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

一、背景

今天使用datax往Oracle中同步数据的时候,报了一个错误,内容如下:

com.alibaba.datax.common.exception.DataXException: Code:[DBUtilErrorCode-07], Description:[读取数据库数据失败. 请检查您的配置的 column/table/where/querySql或者向 DBA 寻求帮助.]. - 执行的SQL为: TRUNCATE TABLE XXX.TABLE_NAME 具体错误信息为:java.sql.SQLException: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

如错误信息提示,资源正忙(被占用),一般为有其他进程占住了这个资源,如 insert/delete/update 操作后没有提交,那么其他进程无法对该表做 truncate 操作。

二、原因分析

出现这个问题的原因是正在执行的操作请求的资源正被其他事务锁定。即上述异常代表有事务没有提交,因为刚好有表正在被操作且被锁,因此资源还未释放,导致处理需要等待资源释放。

之后才搞清楚原来是有人对表执行了 delete 的 sql 语句,然后又突然给中断了,既没 commit 提交,也没 rollback 回滚,而导致的数据库锁表。即由于其他 Session 已经对目标表做了操作,并且已经有排他锁在表上了,所以新的 Session 无法再对表进行 DDL/MDL(除select语句外) 操作。

三、解决办法

方法一:

重启一下数据库服务,当然了,不建议这样做,因为生产环境的数据库很多人在用,所以千万别重启,如果是测试环境,那就视情况而定了。

方法二:

v$locked_object 视图记录锁表相关的内容。这个视图的结果需要有锁表的情况才会出现,主要可以通过它 session_id 来关联其他表。

  • 检查哪个用户占用资源
    session_id:就是 session 会话 id。
    owner:操作表的用户名
    object_name :表名
    根据出问题的表来找到所需要的 session_id
select l.session_id,o.owner,o.object_name 
from v$locked_object l,dba_objects o 
where l.object_id=o.object_id;
  • 利用查出来占用资源的 session_id,查出更加详细的信息
    下面的 sid 就是上面查询出来的 session_id。这个查询将返回会话 ID、序列号、数据库用户名、操作系统用户名、。
SELECT sid, serial#, username, oSUSEr,
terminal,program ,action, prev_exec_start
FROM v$session where sid = 143;
  • 根据上面查出来的 sidserial# 杀掉占用资源的session会话。
    第一个为 sid,第二个为 serial#
alter system kill session '143,29637';

但是有时候 alter system kill session '143,29637'; 语句是 kill 不掉这个 session 的,其实解决办法还有一种比较简单的,根据上面查询的 oSUSEr(某个具体的人,比如 zhangsan),还有 program(程序名称,比如 plsqldev.exe)来确定是谁用的什么工具操作的这个表,并且没有 commit 的话,然后去找他,直接在他操作的客户端上 commit/rollback 一下就可以了。

实际杀死 session 的方法有好多,具体可参考:
https://blog.csdn.net/leo__1990/article/details/90261966

D:>orakill sid  spid (注:cmd命令窗口中执行 只有oracle服务器端才有orakill命令)
example: D:>orakill oemrep 1204
提示:KILL OF THREAD id 1204 IN INSTANCE oemrep successfully signalled.
结果:成功删除该SESSION,表也解锁

四、过程中遇到的问题

  1. 查询表 v$locked_object,提示表或视图不存在
    原因是使用的用户没有相关的查询权限导致,只要给用户附上查询此表的权限就行了(找DBA),如下:
--这个权限比较大
grant select any dictionary to 用户; 
--这个权限是最低的要求,但是可以访问到 v$相关视图
grant select_catalog_role to 用户; 
--收回权限
revoke select_catalog_role from user;
  1. 执行 alter system kill session '143,29637'; 语句时,提示没有权限
    官方文档查到,kill session 需要 ALTER SYSTEM 权限,但是这个权限非常大,一般来说是不能直接给,可以找 DBA 帮忙执行以下上面没有权限的语句。
GRANT ALTER SYSTEM TO 用户;

五、详解

v$locked_object

v$session

参考:
https://blog.csdn.net/u011278012/article/details/51992811
https://blog.csdn.net/chr561314/article/details/6803612
https://blog.csdn.net/enthan809882/article/details/104778556

v$process

参考:
https://blog.csdn.net/enthan809882/article/details/104778556

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值