rollback的进度

  【源自网络】

如果一个会话正在回滚,如何知道回滚的进度?如何知道还需要多长时间才能回滚结束?下面做一个简单的总结:

=========================
一、对于死事务
对死事务,可以查询x$ktuxe: [K]ernel [T]ransaction [U]ndo Transa[x]tion [E]ntry
--for dead transactions
set serverout on
declare
l_start number;
l_end number;
l_interval number :=60;
begin
dbms_output.enable(10000);
select ktuxesiz into l_start from x$ktuxe where KTUXEUSN=10 and KTUXESLT=39 --代表死事务;
dbms_lock.sleep(l_interval);
select ktuxesiz into l_end from x$ktuxe where KTUXEUSN=10 and KTUXESLT=39;
if nvl(l_start,0)<>nvl(l_end,0) then
if nvl(l_start,0)>nvl(l_end,0) then
dbms_output.put_line('Rolling back ! Time est Second:'|| round(l_end/(l_start -l_end)*l_interval,2));
elsif nvl(l_start,0) dbms_output.put_line('Performing DMLs');
end if;
else
dbms_output.put_line('Session is waiting for commit or rollback! Can not estimate finish time ');
end if;
exception
when no_data_found then
dbms_output.put_line('No active transaction');
end;
/

我们不能直接得到回滚所需时间,而是通过取两次事务的undo数据块差与耗费的时间做比较,从而推算出回滚的进度。

=========================
二、对于活动事务

如果是活动的事务,则有多种方法:

1. x$ktuxe
方法和查询死事务一样,只是把条件KTUXEUSN=10 and KTUXESLT=39这个条件去掉即可。
如果是并行rollback,x$ktuxe会有多条记录。目前尚未找到能精确定位到某一个正在的会话在x$ktuxe对应的记录,只是通过一些简单的判断确定具体的记录,然后用和上面类似的方法推算进度。

2. 通过v$transaction推算

这种方法适用于两种情况:
1). 用户或程序正常发出rollback
2). 会话处于活动状态(active)时被kill,且状态为ACTIVE或者KILLED(ORA-00031: session marked for kill)

--for active transactions
set serverout on
declare
l_start number;
l_end number;
l_interval number :=30;
l_sid number;
begin
L_SID:=&sid;
SELECT a.used_ublk into l_start FROM v$transaction a, v$session b WHERE a.addr = b.taddr and sid=L_SID;
dbms_lock.sleep(l_interval);
SELECT a.used_ublk into l_end FROM v$transaction a, v$session b WHERE a.addr = b.taddr and sid=L_SID;
if nvl(l_start,0)<>nvl(l_end,0) then
if nvl(l_start,0)>nvl(l_end,0) then
dbms_output.put_line('Rolling back ! Time est Second:'|| round(l_end/(l_start -l_end)*l_interval,2));
elsif nvl(l_start,0) dbms_output.put_line('Performing DMLs');
end if;
else
dbms_output.put_line('Session is waiting for commit or rollback! Can not estimate finish time ');
end if;
exception
when no_data_found then
dbms_output.put_line('No active transaction');
end;
/

原理和方法和上面提到的都一致,这里不再赘述。这种方法可以精确定位具体的会话。

3. 直接查询v$session_longops

如果满足如下条件:
. 如果数据库版本大于等于10g
. 运行时间超过6秒
. 在会话中发出rollback(命令手工发出或者软件发出)

则进度直接可以通过v$session_longops获得:
--for 10g and above
select * from v$session_longops where sofar<>totalwork and pname='Transaction Rollback';


4: V$FAST_START_TRANSACTIONS
这种方法适用于
1) 实例恢复进度监控
2)对异常中断的事务的回滚的进度(被kill时会话是非活动的,或者被正常kill,没有出现ORA-00031: session marked for kill信息)

这几种情况可以可以查看V$FAST_START_TRANSACTIONS来判断回滚进度。

重要关注这个视图的两个字段:
UNDOBLOCKSDONE:已经回滚了多少undo block
UNDOBLOCKSTOTAL:总共需要回滚多少undo block

如一个有大事务未提交的会话被异常中断,如被kill,我们就可以从后台看到这个被异常中断的会话对应的事务的回滚过程:
SQL> select state,undoblocksdone,undoblockstotal from V$FAST_START_TRANSACTIONS ;

STATE UNDOBLOCKSDONE UNDOBLOCKSTOTAL
---------------- -------------- ---------------
RECOVERING 659 1469

......
SQL> select state,undoblocksdone,undoblockstotal from V$FAST_START_TRANSACTIONS ;

STATE UNDOBLOCKSDONE UNDOBLOCKSTOTAL
---------------- -------------- ---------------
RECOVERED 1469 1469


可以写一个和上面v$transaction方式类似的过程来推算回滚的结束时间。

declare
l_start number;
l_end number;
l_total number;
l_interval number :=30;
begin
select sum(UNDOBLOCKSDONE) ,sum(UNDOBLOCKSTOTAL) into l_start,l_total from V$FAST_START_TRANSACTIONS where state='RECOVERING';
dbms_lock.sleep(l_interval);
select sum(UNDOBLOCKSDONE) into l_end from V$FAST_START_TRANSACTIONS where state='RECOVERING';
dbms_output.put_line('Rolling back ! Time est Second:'|| round((l_total-l_end)/(l_end -l_start)*l_interval,2));
end;
/

这种方法有不完美的地方,就是如果不能精确定位某一个会话的回滚进度;如果数据库不断有新的回滚,则结果可能会不准确。


注意:回滚的进度受很多因素的影响,如数据库、主机的繁忙程度等,所以以上所有方法得到的都是在当时条件下回滚所需时间的估算值,实际所需时间不一定和估算值一样。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/22308399/viewspace-764045/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/22308399/viewspace-764045/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值