前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Oracle中执行truncate操作出现hang

Oracle中执行truncate操作出现hang

作者头像
bisal
发布2021-11-08 10:58:34
5840
发布2021-11-08 10:58:34
举报
文章被收录于专栏:bisal的个人杂货铺

同事说某套Oracle中有一张94G容量的表需要清空,用delete删除的,但是一直卡着。

这个能理解,因为delete是DML操作,事务控制的,在删除的时候,会写入redo、undo等日志,为了能做回滚,或者异常恢复,删除的数据越多,消耗的资源越高,等待时间越久,因此不建议对大量数据的删除使用delete,应该用批量操作,分多个事务执行,分散资源消耗。

针对这个需求,是清空这张表,不用备份,所以应该用truncate,他是DDL操作,不会像delete这种消耗太多的资源。

于是开始执行truncate,

代码语言:javascript
复制
truncate table test;

此时提示错误,

代码语言:javascript
复制
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

他的意思是存在未提交的事务,truncate不能获得锁资源,可以用如下SQL找出锁住的表对象,

代码语言:javascript
复制
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;

可以用如下SQL找出引起锁住的会话,

代码语言:javascript
复制
select b.username,b.sid,b.serial#,logon_time 
from v$locked_object a,v$session b 
where a.session_id = b.sid order by b.logon_time;

有了这个sid和serial#,可以看下他正在执行的是什么SQL,

代码语言:javascript
复制
select distinct c.spid,b.sid,b.username,a.module,a.hash_value,sql_text 
from v$sql a,v$session b,v$process c
where a.hash_value=b.sql_hash_value and a.address=b.sql_address 
and b.paddr=c.addr and b.sid=&sid and b.serial#=&serial;

针对这个案例,看到阻塞会话正执行的是delete,module显示是dbeaver,这正是刚刚同事执行出现hang且未做提交的SQL,

代码语言:javascript
复制
delete from test where 1=1;

确认可删除会话,执行如下SQL,

代码语言:javascript
复制
alter system kill session 'sid,serial#';

此时再次执行,但是一直是hang住的,等了好几分钟,

代码语言:javascript
复制
truncate table test;

正常来讲,truncate应该执行很快,执行慢,说明有等待,看下等的是什么,等待的是"enq: RO - fast object reuse",

df0c2586be716b8e299b0fec56a1382f.png
df0c2586be716b8e299b0fec56a1382f.png

图中显示,session_id=196是truncate,正在阻塞的是session_id=770,他对应的是后台进程CKPT,即检查点进程,

888a7e9535b9524a808de81a3cb45c58.png
888a7e9535b9524a808de81a3cb45c58.png

MOS这篇文章《Resolving Issues Where 'enq: RO - fast object reuse' Contention Seen During Drop or Truncate Operations (Doc ID 1475659.1)》,介绍了下enq: RO - fast object reuse这个等待事件,

The RO enqueue known as "Multiple object resue" enqueue, is used to synchronise operations between foreground process and a background process such as DBWR or CKPT. It is typically used when dropping objects or truncating tables. Following is the sequence of events When a truncate/drop occurs: 1. Foreground process acquires the "RO" enqueue in exclusive mode 2. Cross instance calls (or one call if it is a single object) are issued ("CI" enqueue is acquired) 3. CKPT processes on each of instances requests the DBWR to write the dirty buffers to the disk and invalidate all the clean buffers. 4. After DBWR completes writing all blocks, the foreground process releases the RO enqueue.

大致意思是RO队列是用来同步前台进程(执行truncate、drop等操作)和后台进程操作(DBWR、CKPT)的,这个队列的等待会特别发生在drop删除对象和truncate表的时候。

而且和RO等待以及truncate执行慢相关的bug还是不少的,

1f641d5960914ceac048cd97be879587.png
1f641d5960914ceac048cd97be879587.png

在查资料的过程中,truncate竟然跑完了,14:56-15:15,大约20分钟。这套库很忙,频繁的写入,日志切换很频繁,可能会引起DBWR进程的等待,而执行truncate需要做Checkpoint,同样会等待DBWR,怀疑有无可能这些并发的操作,导致RO等待队列变长,作为临时解决,清除缓存,或者重启数据库,或许可行,当然不排除bug存在的可能。

找机会重现问题,我们再做讨论。

参考资料,

http://www.dboracle.com/archivers/enq-ro-fast-object-reuse%E9%97%AE%E9%A2%98%E5%A4%84%E7%90%86.html

https://www.cnblogs.com/callmemax/p/5958571.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/11/02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档