暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

truncate表报错ORA-00054

原创 董小姐 2024-11-27
552

问题描述

由于一张超大日志表频繁读写导致数据库卡顿,该日志表1.3T大小,有5689256条记录,还有一张日志表1.5T,有32478条记录,2个日志表均有大字段。和业务方沟通后说是可以将表直接truncate。可是正值业务高峰期,truncate提示:资源正忙(被占用)ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

问题原因

ORA-00054 资源正忙(被占用),一般为有其他进程hold住了这个资源,如insert/update/delete信息后没有提交,那么其他进程无法对该表做truncate操作。该情况和两个进程同时对一个资源(如update同一行)进行操作还不同,两个进程同时对一个资源进行操作时,第二个操作会卡住,现象就是在等待,使用sqlplus测试的现象就是回车后卡住,但是truncate会报如上的错误。

场景复现

--会话1 新建一张表,插入一行数据,但是没有提交(commit)
create table dxj(id int);
insert into dxj values('1');

--会话2 想要对此表做truncate,便会报ORA-00054错误
sys@DXJ 2024-11-26 06:46:37> truncate table dxj;
truncate table dxj
               *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

结论:只有当会话1提交后或资源被释放后,会话2的truncate才可以执行。

--会话1  提交(commit)
commit;

--会话2  truncate成功
sys@DXJ 2024-11-26 06:46:43> truncate table dxj;
Table truncated.

解决办法

由于业务高峰期业务已经宕掉,truncate操作也失败,为规避数据不一致或回滚,只能由现场同事向客户说明情况报备申请应用停止然后进行truncate操作。

附加:可以手动kill会话场景处理步骤

找出hold住资源的进程

找出hold住资源的进程,进行commit后释放资源。如无法进行提交的,确认可以停止后将其kill掉即可(慎重慎重,最好上报后确认)。

select b.owner,b.object_name,a.session_id,a.locked_mode from v$locked_object a,dba_objects b where b.object_id = a.object_id;

查询出sid和serial#和锁表sql

select l.session_id sid, 
       s.serial#, 
       l.locked_mode, 
       l.oracle_username, 
       s.user#, 
       l.os_user_name, 
       s.machine, 
       s.terminal, 
       a.sql_text, 
       a.action ,
'alter system kill session ' || '''' || l.session_id || ',' || s.serial# || ''' immediate;'   from v$sqlarea a, v$session s, v$locked_object l 
where l.session_id = s.sid 
   and s.prev_sql_addr = a.address 
order by sid, s.serial#;

Kill会话进程

alter system kill SESSION '399, 14608' immediate;


参考链接:[ORACLE] ORA-00054 错误的解决方案_ora00054-CSDN博客

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论