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

数据库并行恢复案例一则

原创 Eygle 2019-07-24
1285

以下是和并行恢复相关的一个具体案例。

故障起因是由于工程师对一个10G大表进行imp操作,imp语句如下

imp username/passwd file=G:\mobile.dmp log=G:\ mobile_old.log ignore=y buffer=8192000 feedback=10000

这里导出文件mobile.dmp的大小有6G,由于失误未使用commit=y参数,这导致导入数据没有分批量提交,当导入执行了几个小时后,由于对业务系统产生了极大的压力和影响,imp操作被强行中断,这个中断导致了这个大事务的回滚,噩梦从此开始。

随后对该对象的Trucate/Drop操作都随之挂起,系统开始回滚,检查回滚段可以找到这个大事务的回滚段:

SQL> select * from v$rollstat where xacts >0;
USN LATCH EXTENTS     RSSIZE WRITES XACTS   GETS WAITS OPTSIZE    HWMSIZE SHRINKS  WRAPS EXTENDS  AVESHRINK  AVEACTIVE STATUS CUREXT CURBLK
--- ----- ------- ---------- ------ ----- ------ ----- ------- ---------- -------- ----- ------- ---------- ---------- ------ ------ ------
  3     3    3571 2066300928      0     1 445173    41         2066300928       0      0       0          0          0 ONLINE   3569    159

注意到这个回滚段已经扩展到2,066,300,928 Bytes大小,也就是约2G大小,这个回滚段所涵盖的数据都需要回滚。初始的系统参数FAST_START_PARALLEL_ROLLBACK设置为LOW:

SQL> show parameter parallel_rollback
NAME                                 TYPE        VALUE
------------------------------------ ----------- -----------------------------
fast_start_parallel_rollback         string      LOW
SQL> show parameter cpu_count
NAME                                 TYPE        VALUE
------------------------------------ ----------- -----------------------------
cpu_count                            integer     4

系统启动了8个并行进程进行并行回滚,但是回滚执行了10个多小时仍然未完成(v$session的等待事件显示并行恢复产生了竞争,在此类情况下,通常串行恢复是更适宜的):

SQL>  select sid,program,event from v$session where PROGRAM like '%P%';
       SID PROGRAM              EVENT
---------- -------------------- ----------------------------------------
       533 ORACLE.EXE (P003)    db file sequential read
       534 ORACLE.EXE (P006)    db file sequential read
       535 ORACLE.EXE (P007)    wait for a undo record
       536 ORACLE.EXE (P004)    db file sequential read
       537 ORACLE.EXE (P005)    db file sequential read
       538 ORACLE.EXE (P002)    wait for a undo record
       540 ORACLE.EXE (P000)    wait for a undo record
       541 ORACLE.EXE (P001)    db file sequential read
       550 ORACLE.EXE (CKPT)    rdbms ipc message
       554 ORACLE.EXE (PSP0)    rdbms ipc message
       555 ORACLE.EXE (PMON)    pmon timer

随后尝试修改了FAST_START_PARALLEL_ROLLBACK设置为HIGH,然后数据库启动了16个并行进程进行恢复:

Wed Jan 24 09:21:06 2007
SMON: parallel recovery restart with degree=16 (!=8)
Wed Jan 24 09:21:18 2007
SMON: Restarting fast_start parallel rollback
Wed Jan 24 09:21:19 2007
ALTER SYSTEM SET fast_start_parallel_rollback='HIGH' SCOPE=BOTH;
这个恢复最终持续了一个小时左右,以SMON出错而结束,最后SMON终止了16个并行进程,启动了一个恢复进程进行恢复,smon的TRACE文件报了如下信息:
*** 2007-01-24 09:21:06.334
*** SERVICE NAME:(SYS$BACKGROUND) 2007-01-24 09:21:06.318
*** SESSION ID:(549.1) 2007-01-24 09:21:06.318
*** 2007-01-24 09:21:06.334
SMON: parallel recovery restart with degree=16 (!=8)
Parallel Transaction recovery caught exception 30312
*** 2007-01-24 09:21:18.553
Parallel Transaction recovery caught error 30312
*** 2007-01-24 09:21:18.553
SMON: Restarting fast_start parallel rollback
*** 2007-01-24 11:16:17.697
Parallel Transaction recovery caught exception 12801
Parallel Transaction recovery caught error 370
*** 2007-01-24 11:16:20.885
SMON: Restarting fast_start parallel rollback
Dead transaction 0x0003.028.00017d2a recovered by 1 server(s)

最后两行至为关键,Oracle通过1个Server进程进行恢复,通过查询视图V$FAST_START_TRANSACTIONS,可以发现恢复的速度加快了许多:

SQL> select usn,undoblockdone,undoblockstotal,cputime from V$FAST_START_TRANSACTIONS;
  USN       UNDOBLOCKSDONE      UNDOBLOCKSTOTAL      CPUTIME
---------- ---------------      -------------------  ---------------
  3          1036                203328              8208  
SQL> select * from V$FAST_START_SERVERS;
STATE       UNDOBLOCKSDONE        PID XID
----------- -------------- ---------- ----------------
RECOVERING          1036         16 030028002A7D0100

UNDOBLOCKSDONE表示已经恢复的回滚段块,UNDOBLOCKSTOTAL表示需要恢复的回滚段块总量,可以看出,回滚段3在参与恢复的操作,203328中有1036块已经恢复,cpu占用了8208秒。最终再通过近3个小时的恢复,数据库完成了这次灾难性的回滚。

从v$fast_start_transactions视图我们可以看到具体信息,恢复共花费了10255秒的时间,而平均每秒数据库仅对约20个UNDO BLOCK完成了回滚:

SQL> select * from v$fast_start_transactions;
USN SLT   SEQ STATE     UNDOBLOCKSDONE UNDOBLOCKSTOTAL CPUTIME  XID              RCVSERVERS
--- --- ----- --------- -------------- --------------- -------  ---------------- ----------
 3  40 97578 RECOVERED         203328          203328   10255  030028002A7D0100          1

通过这个案例我们知道Oracle的并行回滚有时候并不可靠,而且的确还存在大量的Bug,从Oracle的官方网站上可以找到大量类似的案例。

SMON对于死事务执行恢复,如果事务很大,Oracle将首先尝试并行恢复,并行恢复Oracle将采用intra-transaction并行恢复,也就是使用多个并行进程恢复死事务,如果intra-transaction并行恢复失败,SMON将指定单进程进行恢复,这个恢复过程将会十分缓慢,特别是当事务很大时。在恢复期间,SMON进程还可能停止其他类别的服务,如排序段请求、实例恢复请求等,同时还可能导致查询十分缓慢(由于大量的CR回滚等),从外在看来,数据库就可能处于停顿状态。这些问题最终被定义为一个Bug,Oracle在Oracle 11g中进行了改进。

然而这种问题应该极少被遇到,做为一个DBA也应该避免陷于这样的境地,将这个案例收录于此,供大家借鉴。


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

评论