DATAGUARD 主从同步GAP超过xxx小时
一、数据库状态检查的步骤/命令(通过本步骤可以确定数据库当前的状态是否OK)
1.检查备库数据库的状态
SELECT open_mode FROM V$DATABASE;
OPEN_MODE
--------------------
READ ONLY WITH APPLY
2.检查备库MRP进程是否正常:
select process,CLIENT_PROCESS,status,thread#,sequence# from v$managed_standby;
查看mrp进程是否处于APPLYING_LOG状态
二、请描述告警出现的可能原因
1.可能是因为主库产生大量的归档日志,导致同步应用延迟
2.可能是日志同步慢造成,此时可能是因为网络问题,或者日志量大,获取其他原因
3.可能是因为备库日志应用慢造成,此时备库在应用日志时因为多余的等待而变慢
4.可能是因为部分还未来得及应用便被删除,造成了GAP。
三、预计多久不处理就可以出现UIOC(P1)
1.主要视备库是否有实时性要求比较高的查询业务,根据不同业务需求紧急度不同
四、告警检查的步骤(通过本步骤确定告警是否是误告)
1.检查当前延迟情况(是同步延迟还是应用延迟?)
(1)查询lag情况:
select to_char(SYSDATE,'yyyymmdd hh24:mi:ss') CTIME,NAME,VALUE,DATUM_TIME from V$DATAGUARD_STATS WHERE NAME LIKE '%lag';
(2)排查主备库告警日志情况,是否明显的gap
(3)判断日志应用的情况,看APPLIED
set line 180 pages 9999
col NAME for a65
select * from (SELECT SEQUENCE#, APPLIED, CREATOR, NAME
FROM GV$ARCHIVED_LOG
order by sequence# desc) where rownum=to_char(sysdate-11)
GROUP BY SUBSTR(TO_CHAR(first_time, 'MM/DD/RR HH:MI:SS'),1,5)
ORDER BY SUBSTR(TO_CHAR(first_time, 'MM/DD/RR HH:MI:SS'),1,5) DESC;
(2)排查告警日志,以上检查步骤等,确定当前日志同步及应用是否正常进行,如果是正常,则只能是尽量等待慢慢追赶。如果同步应用速度太慢,明显无法赶上日常新赶上情况,则需进一步排查。
(3)如果出现日志传输到备库且尚未被应用,但已经被删除掉。
1)检查主库是否存在缺失的归档日志,如果存在,则直接取归档过来备库进行应用。
2)如果主库已经不存在,可以让备份组帮忙恢复指定的归档到备库进行应用。
3)如果缺失的归档太多,且恢复比较困难,则可以考虑进行增备恢复。
增备方案示例:
1.----备库取消归档应用
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;
2.----备库确定lowest scn
col current_scn for 99999999999999
SELECT CURRENT_SCN FROM V$DATABASE;
select min(fhscn) from x$kcvfh;
select min(f.fhscn) from x$kcvfh f, v$datafile d
where f.hxfil =d.file#
and d.enabled != 'READ ONLY' ;
取上述查询中的最小值
3.-----on primary db 端根据第2步中获取的最小scn 来进行增量备份
BACKUP INCREMENTAL FROM SCN 1676552 DATABASE FORMAT '/data/ora/ForStandby_%U' tag 'FORSTANDBY';
Eg:
RMAN> run {
allocate channel t1 device type disk;
allocate channel t2 device type disk;
allocate channel t3 device type disk;
allocate channel t4 device type disk;
BACKUP as compressed backupset INCREMENTAL FROM SCN 5992377
DATABASE FORMAT '/opt/app/oracle/fast_recovery_area/ORCL/backupset/2021_09_24/orc_%U.bak';
}
4.-----拷贝备份到 备库
$scp ForStandby_07pqprm4_1_1 192.168.0.10:/tmp
5.----on standby db 在备库端注册备份片,注意用户属主,权限
RMAN> CATALOG START WITH '/lixora/ForStandby';
6.----执行恢复
RMAN> RECOVER DATABASE NOREDO;
7.-----on primary db 生成新的standby 控制文件
RMAN> BACKUP CURRENT CONTROLFILE FOR STANDBY FORMAT '/tmp/ForStandbyCTRL.bck';
8.----把主库端生成的standby 控制文件拷贝到备库,注意用户属主,权限
RMAN> BACKUP CURRENT CONTROLFILE FOR STANDBY FORMAT '/lixora/ForStandbyCTRL.bck';
scp /lixora/ForStandbyCTRL.bck 192.168.0.10:/tmp
9.------备份备库数据文件信息,用于在恢复新的standby控制文件后比对
spool datafile_names_step8.txt
set lines 200
col name format a60
select file#, name from v$datafile order by file# ;
spool off
10.------on standby Db 恢复新的standby 控制文件
RMAN> SHUTDOWN IMMEDIATE ;
RMAN> STARTUP NOMOUNT;
RMAN> RESTORE STANDBY CONTROLFILE FROM '/tmp/ForStandbyCTRL.bck';
11.-----更新控制文件中的数据文件信息
使新的standby 控制文件生效
RMAN> SHUTDOWN;
RMAN> STARTUP MOUNT;
CATALOG START WITH '+DATA/zhglptdg/datafile/';
12.------on primary db。确保在备库发生日志gap 后,主库没有添加过新的数据文件。
SELECT FILE#, NAME FROM V$DATAFILE WHERE CREATION_CHANGE# > 12611050666604;
如果有记录,则不能进行switch 操作,可以参考一下文档来恢复:
rman 增量恢复 dg gap后 主库添加新数据文件
Note 1531031.1 Steps to perform for Rolling forward a standby database using RMAN incremental backup when datafile is added to primary
13.-----重命名数据文件
RMAN> SWITCH DATABASE TO COPY;
14.-----再次确认在恢复增量备份片后主库和备库scn 差距没有太大
SQL> col current_scn for 99999999999999
SELECT CURRENT_SCN FROM V$DATABASE;
select min(fhscn) from x$kcvfh;
select min(f.fhscn) from x$kcvfh f, v$datafile d
where f.hxfil =d.file#
and d.enabled != 'READ ONLY' ;
2.针对网络问题造成的同步慢的情况,通过手工从主库scp一个文件到备库观察传输速度,验证网络是否存在问题。
3.针对备库应用日志慢的情况
观察数据库mrp及prxx进程的等待事件情况,如果出现特殊等待事件,需要上报排查。
select event,p1,p2,p3 ,program from v$session;
4.针对明显的日志GAP情况,请参考步骤1。
八、验证问题已经恢复的步骤和命令
1.检查当前延迟情况(是同步延迟还是应用延迟?)
(1)查询lag情况:
select to_char(SYSDATE,'yyyymmdd hh24:mi:ss') CTIME,NAME,VALUE,DATUM_TIME from V$DATAGUARD_STATS WHERE NAME LIKE '%lag';
(2)排查主备库告警日志情况,是否明显的gap
(3)判断日志应用的情况,看APPLIED
set line 180 pages 9999
col NAME for a65
select * from (SELECT SEQUENCE#, APPLIED, CREATOR, NAME
FROM GV$ARCHIVED_LOG
order by sequence# desc) where rownum @$ORACLE_HOME/rdbms/admin/awrrpt.sql
可以通过下面方法在另一个好的实例收集AWR
SELECT output FROM TABLE(DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML( 3616491197, 1, 61143, 61144) ) ;
4.补充收集Alert log/trace file、AWR/ASH、OSW。进一步分析;必要时需要寻求oracle support的支持。
5.开SR并将以上收集信息上传SR,对于4031 的深入以及代码层面分析,Oracle 后台研发一般需要heapdump 或者 library cache dump 进行分析.
六、需要反馈上级以及运营的信息
七、建议处理的流程,步骤和对应命令
1.初步排查:
一般应急状况下,处理的第一时间不用去检查共享池碎片,意义不大。而且4031错误同样有可能导致整个数据库实例hang,所以应该去检查什么组件大小比较异常(有条件的话同类似的其他库环境去对比)
Select t.*
From (Select Name,
bytes / (1024 *1024) "MB",
round(bytes /(Select Value
From v$parameter t
Where t.name = 'shared_pool_size') * 100,
2) || '%'"USED%"
From v$sgastat
Where pool = 'shared pool'
Order By 2 Desc) t
Where rownum < 20;
根据当前组件大小状态,判断是哪部分出了问题,如果是可以回收空间的组件,条件允许的话通过flush shared_pool来处理。比如sql area、Ccursor等占据主要大小,可能与硬解析有关,可以通过下面的查询确认:
SET pages 10000
SET linesize 200
column FORCE_MATCHING_SIGNATURE format 99999999999999999999999
with c as
(select force_matching_signature,count(*) cnt
from v$sqlarea
where force_matching_signature!= 0
group by force_matching_signature
having count(*) > 20),
sq as
(select sql_text,
force_matching_signature,
row_number() over (partition by force_matching_signature order by sql_id desc) p
from v$sqlarea s
where force_matching_signature in
(select force_matching_signature from c))
select sq.sql_text, sq.force_matching_signature, c.cnt "unsharedcount"
from c, sq
where sq.force_matching_signature= c.force_matching_signature
and sq.p = 1order by c.cnt desc;
如果是无法回收的perm组件,则必须重启实例。临时的一个解决方法是,内存空间足够的情况下,内存中调大sharedpool,等到临时窗口后再重启实例恢复。
Select pool, Sum(bytes) / (1024 * 1024) "MB"
From v$sgastat
Where pool = 'shared pool'
Group By pool;
2. 以下应急方案在可行的情况下可以逐一尝试:
(1)调大问题池的 size,例如调大 shared pool 的大小,可暂时缓解ORA-04031,争取分析的时间,然后在空闲时段进行数据库实例重启。
alter system set shared_pool_size= xxG;
需要判断是否可以调大shared_pool_size,一般可通过如下方式
select NAME,VALUE/1024/1024 from v$parameter where name in('shared_pool_size','db_cache_size','sga_target','sga_max_size')
union
select component,current_size/1024/1024 from v$sga_dynamic_components where component in ('shared pool','DEFAULT buffer cache','large pool');
NAME VALUE/1024/1024
------------------------------ ---------------
DEFAULT buffer cache 400-->buffer cache当前实际分配内存大
db_cache_size 304-->为SGA中占用内存db_cache_size参数设定值
large pool 16
sga_max_size 3072
sga_target 2048
shared pool 1504-->shared pool 当前实际分配内存大小
shared_pool_size 1008-->为SGA中占用内存shared_pool_size参数设定值。
7 rows selected.
满足如下条件才可调整:
如果sga_max_size 实际比各个内存池大小加起来大很多,则可以调大shared_pool_size。
(2)不繁忙的系统,可以尝试flushshared pool (发生问题的是shared pool的前提下,但在很多情况下可能不会奏效,会很快又出现ORA-04031的问题)
alter system flush shared_pool ;
(3)重启故障数据库实例
在重启或者刷新shared_pool前,收集相关信息留做进一步的根因诊断。
八、验证问题已经恢复的步骤和命令
1.检查告警日志是否仍然报错。
Oracle HANG库应急预案
说明: 本文档不针对具体异常进行前置具体分析,目的是针对紧急故障进行快速应急恢复
数据库 HANG 的表现为:数据库出现大量等待(row cache object/library cache lock/library cache lock/library cache pin/library cache: mutex X 等)、前台无法登陆、登陆时 plsql dev 或页面出现卡顿、后台无法登陆,严重时出现 OS 命令卡顿等现象。
具体原因可能是:数据库出现大量等待事件、主机 CPU/内存使用率异常、连接数满等,这些往往已经影响到应用可用性,需要立刻处理。
1、收集 HANGANALYZE(5-10分钟)(可选)
说明: 该步骤目的为采集故障现场信息,结合紧急程度判断,非常紧急情况可跳过该步骤
sqlplus / as sysdba (后台无法登陆时使用sqlplus -prelim / as sysdba)
SQL> oradebug setmypid (sqlplus -prelim / as sysdba 时使用oradebug setospid )
Statement processed.
SQL> oradebug unlimit
Statement processed.
SQL> oradebug hanganalyze 3 (RAC 环境使用oradebug -g all hanganalyze 3)
等待 1 分钟
SQL> oradebug hanganalyze 3 (RAC 环境使用oradebug -g all hanganalyze 3)
等待 1 分钟
SQL> oradebug dump systemstate 10 (RAC 环境使用oradebug -g all dump systemstate 10)
等待 1 分钟
SQL> oradebug dump systemstate 10 (RAC 环境使用oradebug -g all dump systemstate 10)
等待 1 分钟
SQL> oradebug tracefile_name --------保留 trace 文件
2、全量KILL SESSION(4分钟)
在异常的数据库节点,进行KILL所有 SESSION操作,这里分两种情况:
2.1、情况一:如果能登录数据库(4分钟)
2.1.1、检查占用undo超过50MB的事务,目的在于避免大事务异常回滚需要较长时间,非常重要!!!(0.5分钟)
set linesize 180 pagesize 999
spool /tmp/undo_sess.txt
select inst_id,sid,serial#,xidusn,undo_size_m,sess_status,status,username,sql_id,prev_sql_id,machine,start_time,logon_time,related_rows,sql_text
from (select t.xidusn,s.status sess_status,t.status,s.inst_id,s.sid,s.sql_id,s.prev_sql_id,s.serial#,s.username,s.machine,t.start_time,s.logon_time,t.used_urec related_rows, round(t.used_ublk * block_size / 1024 / 1024, 0) undo_size_m,q.sql_text
from gv$session s,
gv$transaction t,
dba_tablespaces dt,
gv$system_parameter p,
gv$sql q
where q.sql_id(+) = s.sql_id and upper(p.name) = 'UNDO_TABLESPACE' and dt.tablespace_name = p.value and t.inst_id = s.inst_id and p.inst_id = s.inst_id and s.saddr = t.ses_addr
and round(t.used_ublk * block_size / 1024 / 1024, 2) > 50
order by t.used_ublk desc) t where rownum < 20;
spool off
说明:
- 如有返回,undo_size_m为占用undo大小,需要记录对应的sid。然后转> 步骤2.1.2 KILL SESSION
- 如无返回,直接进入> 步骤2.1.2 KILL SESSION
2.1.2、记录当前所有用户SESSION对应的OS进程,生成OS级kill -9脚本(注意有占用undo的SESSION需要排除)(0.5分钟)
set head off
set feedback off
set pagesize 0
spool /tmp/kill_9_1.sh
select ' kill -9 ' || spid from (select spid from v$process where addr in(select paddr from v$session where username is not null
--and sid not in ()
));
spool off
2.1.3、生成数据库KILL SESSION脚本 (0.5分钟)
set head off
set feedback off
set linesize 180 pagesize 0
spool /tmp/kill_sess_1.sql
select 'alter system kill session '''||sid||','||serial#||''' immediate;' from v$session where username is not null
--and sid not in ()
;
spool off
2.1.4、执行kill_sess_1.sql脚本(0.5分钟)
SQL>@/tmp/kill_sess_1.sql
如果session kill之后不能2分钟内不能释放执行OS级kill -9脚本
sh /tmp/kill_9_1.sh
说明:
如果上述kill session无法恢复应用,转步骤3。
数据库恢复正常,后续步骤不需要处理。
2.2、情况二:如果登不进数据库(2分钟)
如果sqlplus 登入hang住或者报ORA-00020连接数满,则在主机层面kill会话,为防止 SID 有相似的地方,这里使用精确匹配:(2分钟)
ps -ef|grep -v grep|grep LOCAL=NO|grep -w oracle$ORACLE_SID |awk '{print $2}'|xargs kill -9
说明:
如果上述kill OS会话无法恢复应用,转步骤3。
如果数据库恢复正常,后续步骤不需要处理。
3、检查ORA-00600/ORA-07445报错 (2 分钟)
执行下面命令查看后台alert日志,确认日志中是否有指定的ORA-00600/ORA-07445报错,无则转步骤4,有则转步骤5
tail -20000 alert_$ORACLE_SID.log |egrep -C5 'ORA-00600.*kghfrh:ds.*|ORA-00600.*kjbldynfr:!llink.*|ORA-00600.*kjcv_move_set_level:WRAP.*|ORA-00600.*kjxmgmb_nreq:!bat.*|ORA-00600.*kghfrmrg:nxt.*|ORA-00600.*ktugnb:clschk_kcbne.*|ORA-00600.*kkqcbydrv:saved value.*|ORA-00600.*kdBlkCheckError.*|ORA-00600.*KFFMLOCK.*|ORA-00600.*opiexe.*|ORA-00600.*kghssgfr.*|ORA-00600.*kglbrk-bad-lock.*|ORA-00600.*kgllkdl-bad-session.*|ORA-00600.*kglLockOwnersListDelete.*|ORA-00600.*kglpnal-bad-pinid.*|ORA-00600.*kghfrmrg:prv.*|ORA-00600.*17182.*|ORA-00600.*17147.*|ORA-00600.*17112.*|ORA-00600.*17163.*|ORA-00600.*17110.*|ORA-00600.*kss_get_type: bad control.*|ORA-07445.*kghfre.*|ORA-07445.*kcbzwb.*|ORA-07445.*kglsim_upd_newhp.*|ORA-07445.*kfupsiternext.*|ORA-07445.*kksParentHandleFreeCbk.*|ORA-07445.*kgldafr.*|ORA-07445.*kglntclr.*|ORA-07445.*kghalf.*'
4、重启监听方案 (4 分钟)
4.1、临时屏蔽 crontab
>cron_null
crontab cron_null
4.2、停监听
需要先同运营确认是否可以停监听,注意$ORACLE_SID需要替换,而且有的库存在多个监听,都要停掉
GI 单实例:crsctl stop res $ORACLE_SID.lsnr -f
RAC 环境:srvctl stop listener -l $ORACLE_SID
VCS 单实例:lsnrctl stop $ORACLE_SID
4.3、kill OS会话
为防止 SID 有相似的地方,这里使用精确匹配
ps -ef|grep -v grep|grep LOCAL=NO|grep -w oracle$ORACLE_SID |awk '{print $2}'|xargs kill -9
4.4、后台登陆数据库会话及检查等待事件是否已释放
这一步特别重要,确认已正常则继续4.5-4.7,如果还不正常则转> 5重启数据库方案
--检查连接数,使用率已下降
select 'session:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$session) a
where s.NAME = 'sessions'
union
select 'process:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$process) a
where s.NAME = 'processes';
--检查等待事件,已恢复正常
set lines 180 pages 999
column event format a60
select event, count(*) as amount
from v$session
where event is not null
and wait_class 'Idle'
group by event
order by count(*) desc;
4.5、启动监听
GI 单实例:crsctl start res $ORACLE_SID.lsnr
RAC 环境:srvctl start listener -l $ORACLE_SID
VCS 单实例:lsnrctl start $ORACLE_SID
4.6、启动 crontab
crontab .cron_file
4.7、前台验证连通性,并通知运营检查应用
5、重启数据库方案(10分钟)
5.1、前置检查步骤(1分钟)
a.检查undo占用
--检查是否有活跃会话占用大于50M的undo
set linesize 180 pagesize 999
select inst_id,sid,serial#,xidusn,undo_size_m,sess_status,status,username,sql_id,prev_sql_id,machine,start_time,logon_time,related_rows,sql_text
from (select t.xidusn,s.status sess_status,t.status,s.inst_id,s.sid,s.sql_id,s.prev_sql_id,s.serial#,s.username,s.machine,t.start_time,s.logon_time,t.used_urec related_rows, round(t.used_ublk * block_size / 1024 / 1024, 0) undo_size_m,q.sql_text
from gv$session s,
gv$transaction t,
dba_tablespaces dt,
gv$system_parameter p,
gv$sql q
where q.sql_id(+) = s.sql_id and upper(p.name) = 'UNDO_TABLESPACE' and dt.tablespace_name = p.value and t.inst_id = s.inst_id and p.inst_id = s.inst_id and s.saddr = t.ses_addr
and round(t.used_ublk * block_size / 1024 / 1024, 2) > 50
order by t.used_ublk desc) t where rownum < 20;
--检查正在回滚的事务占用undo大小
select a.inst_id,(select s.instance_name from gv$instance s where s.INST_ID= a.INST_ID ) instance_name,usn,slt,state,pid,
a.undoblockstotal ,a.undoblocksdone "Done",a.undoblockstotal - a.undoblocksdone "ToDo",to_char(sysdate, 'yyyy-mm-ddhh24:mi:ss')
"Now",round((a.undoblockstotal -a.undoblocksdone)/(a.undoblocksdone / a.cputime)/60,2) "Need_time_min",round(a.undoblockstotal * 8192 / 1024 / 1024 / 1024,2) ||' G' "Undo_used_gb",decode(cputime,0,'unknown',to_char(sysdate +(((undoblockstotal -undoblocksdone) /(undoblocksdone / cputime)) / 86400),'yyyy-mm-ddhh24:mi:ss')) "Estimatedtime to complete"
from gv$fast_start_transactions a
where state ='RECOVERING';
b.检查MTTR时间
set linesize 180
select recovery_estimated_ios,
actual_redo_blks,
target_redo_blks,
log_file_size_redo_blks,
target_mttr,
estimated_mttr
from v$instance_recovery;
说明: 如果没有大undo占用并且$instance_recovery.estimated_mttr小于600秒,可以立即关闭数据库,否则建议延迟关闭。
5.2、关闭数据库(不分架构)(6分钟)
5.2.1、正常关闭数据库(5分钟)
show parameter job_queue_processes
show parameter aq_tm_processes
alter system set job_queue_processes=0 scope=both;
alter system set aq_tm_processes=0 scope=both;
alter system switch logfile; --停主库前多次switch logfile
alter system switch logfile;
alter system switch logfile;
alter system archive log current;
alter system checkpoint; --做一个检查点
shutdown immediate
说明:如果在5分钟后,关闭还未结束,alert.log中没有相关的关闭信息,执行步骤5.2.2
5.2.2、强制关闭数据库(1分钟)(风险较大,请升级部门长确认方案)
shutdown abort
5.3、启动数据库
5.3.1、如果前面是正常停库
startup
5.3.2、如果前面是非正常停库
create pfile=’/tmp/inittemp.ora’ from spfile;
然后修改新生成的 /tmp/inittemp.ora 参数文件中的设置
设置或修改 fast_start_parallel_rollback=high
启动数据库
startup pfile=’/tmp/inittemp.ora’
使用原参数文件重启数据库
shutdown immediate
startup
5.4、后台登陆数据库会话及检查等待事件,前台验证连通性,并通知运营检查应用
--检查连接数,使用率已下降
select 'session:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$session) a
where s.NAME = 'sessions'
union
select 'process:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$process) a
where s.NAME = 'processes';
--检查等待事件,已恢复正常
set lines 180 pages 999
column event format a60
select event, count(*) as amount
from v$session
where event is not null
and wait_class 'Idle'
group by event
order by count(*) desc;
如果前面有停监听记得启动监听
GI 单实例:crsctl start res $ORACLE_SID.lsnr
RAC 环境:srvctl start listener -l $ORACLE_SID
VCS 单实例:lsnrctl start $ORACLE_SID
Oracle HANG库应急预案
说明: 本文档不针对具体异常进行前置具体分析,目的是针对紧急故障进行快速应急恢复
数据库 HANG 的表现为:数据库出现大量等待(row cache object/library cache lock/library cache lock/library cache pin/library cache: mutex X 等)、前台无法登陆、登陆时 plsql dev 或页面出现卡顿、后台无法登陆,严重时出现 OS 命令卡顿等现象。
具体原因可能是:数据库出现大量等待事件、主机 CPU/内存使用率异常、连接数满等,这些往往已经影响到应用可用性,需要立刻处理。
1、收集 HANGANALYZE(5-10分钟)(可选)
说明: 该步骤目的为采集故障现场信息,结合紧急程度判断,非常紧急情况可跳过该步骤
sqlplus / as sysdba (后台无法登陆时使用sqlplus -prelim / as sysdba)
SQL> oradebug setmypid (sqlplus -prelim / as sysdba 时使用oradebug setospid )
Statement processed.
SQL> oradebug unlimit
Statement processed.
SQL> oradebug hanganalyze 3 (RAC 环境使用oradebug -g all hanganalyze 3)
等待 1 分钟
SQL> oradebug hanganalyze 3 (RAC 环境使用oradebug -g all hanganalyze 3)
等待 1 分钟
SQL> oradebug dump systemstate 10 (RAC 环境使用oradebug -g all dump systemstate 10)
等待 1 分钟
SQL> oradebug dump systemstate 10 (RAC 环境使用oradebug -g all dump systemstate 10)
等待 1 分钟
SQL> oradebug tracefile_name --------保留 trace 文件
2、全量KILL SESSION(4分钟)
在异常的数据库节点,进行KILL所有 SESSION操作,这里分两种情况:
2.1、情况一:如果能登录数据库(4分钟)
2.1.1、检查占用undo超过50MB的事务,目的在于避免大事务异常回滚需要较长时间,非常重要!!!(0.5分钟)
set linesize 180 pagesize 999
spool /tmp/undo_sess.txt
select inst_id,sid,serial#,xidusn,undo_size_m,sess_status,status,username,sql_id,prev_sql_id,machine,start_time,logon_time,related_rows,sql_text
from (select t.xidusn,s.status sess_status,t.status,s.inst_id,s.sid,s.sql_id,s.prev_sql_id,s.serial#,s.username,s.machine,t.start_time,s.logon_time,t.used_urec related_rows, round(t.used_ublk * block_size / 1024 / 1024, 0) undo_size_m,q.sql_text
from gv$session s,
gv$transaction t,
dba_tablespaces dt,
gv$system_parameter p,
gv$sql q
where q.sql_id(+) = s.sql_id and upper(p.name) = 'UNDO_TABLESPACE' and dt.tablespace_name = p.value and t.inst_id = s.inst_id and p.inst_id = s.inst_id and s.saddr = t.ses_addr
and round(t.used_ublk * block_size / 1024 / 1024, 2) > 50
order by t.used_ublk desc) t where rownum < 20;
spool off
说明:
- 如有返回,undo_size_m为占用undo大小,需要记录对应的sid。然后转> 步骤2.1.2 KILL SESSION
- 如无返回,直接进入> 步骤2.1.2 KILL SESSION
2.1.2、记录当前所有用户SESSION对应的OS进程,生成OS级kill -9脚本(注意有占用undo的SESSION需要排除)(0.5分钟)
set head off
set feedback off
set pagesize 0
spool /tmp/kill_9_1.sh
select ' kill -9 ' || spid from (select spid from v$process where addr in(select paddr from v$session where username is not null
--and sid not in ()
));
spool off
2.1.3、生成数据库KILL SESSION脚本 (0.5分钟)
set head off
set feedback off
set linesize 180 pagesize 0
spool /tmp/kill_sess_1.sql
select 'alter system kill session '''||sid||','||serial#||''' immediate;' from v$session where username is not null
--and sid not in ()
;
spool off
2.1.4、执行kill_sess_1.sql脚本(0.5分钟)
SQL>@/tmp/kill_sess_1.sql
如果session kill之后不能2分钟内不能释放执行OS级kill -9脚本
sh /tmp/kill_9_1.sh
说明:
如果上述kill session无法恢复应用,转步骤3。
数据库恢复正常,后续步骤不需要处理。
2.2、情况二:如果登不进数据库(2分钟)
如果sqlplus 登入hang住或者报ORA-00020连接数满,则在主机层面kill会话,为防止 SID 有相似的地方,这里使用精确匹配:(2分钟)
ps -ef|grep -v grep|grep LOCAL=NO|grep -w oracle$ORACLE_SID |awk '{print $2}'|xargs kill -9
说明:
如果上述kill OS会话无法恢复应用,转步骤3。
如果数据库恢复正常,后续步骤不需要处理。
3、检查ORA-00600/ORA-07445报错 (2 分钟)
执行下面命令查看后台alert日志,确认日志中是否有指定的ORA-00600/ORA-07445报错,无则转步骤4,有则转步骤5
tail -20000 alert_$ORACLE_SID.log |egrep -C5 'ORA-00600.*kghfrh:ds.*|ORA-00600.*kjbldynfr:!llink.*|ORA-00600.*kjcv_move_set_level:WRAP.*|ORA-00600.*kjxmgmb_nreq:!bat.*|ORA-00600.*kghfrmrg:nxt.*|ORA-00600.*ktugnb:clschk_kcbne.*|ORA-00600.*kkqcbydrv:saved value.*|ORA-00600.*kdBlkCheckError.*|ORA-00600.*KFFMLOCK.*|ORA-00600.*opiexe.*|ORA-00600.*kghssgfr.*|ORA-00600.*kglbrk-bad-lock.*|ORA-00600.*kgllkdl-bad-session.*|ORA-00600.*kglLockOwnersListDelete.*|ORA-00600.*kglpnal-bad-pinid.*|ORA-00600.*kghfrmrg:prv.*|ORA-00600.*17182.*|ORA-00600.*17147.*|ORA-00600.*17112.*|ORA-00600.*17163.*|ORA-00600.*17110.*|ORA-00600.*kss_get_type: bad control.*|ORA-07445.*kghfre.*|ORA-07445.*kcbzwb.*|ORA-07445.*kglsim_upd_newhp.*|ORA-07445.*kfupsiternext.*|ORA-07445.*kksParentHandleFreeCbk.*|ORA-07445.*kgldafr.*|ORA-07445.*kglntclr.*|ORA-07445.*kghalf.*'
4、重启监听方案 (4 分钟)
4.1、临时屏蔽 crontab
>cron_null
crontab cron_null
4.2、停监听
需要先同运营确认是否可以停监听,注意$ORACLE_SID需要替换,而且有的库存在多个监听,都要停掉
GI 单实例:crsctl stop res $ORACLE_SID.lsnr -f
RAC 环境:srvctl stop listener -l $ORACLE_SID
VCS 单实例:lsnrctl stop $ORACLE_SID
4.3、kill OS会话
为防止 SID 有相似的地方,这里使用精确匹配
ps -ef|grep -v grep|grep LOCAL=NO|grep -w oracle$ORACLE_SID |awk '{print $2}'|xargs kill -9
4.4、后台登陆数据库会话及检查等待事件是否已释放
这一步特别重要,确认已正常则继续4.5-4.7,如果还不正常则转> 5重启数据库方案
--检查连接数,使用率已下降
select 'session:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$session) a
where s.NAME = 'sessions'
union
select 'process:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$process) a
where s.NAME = 'processes';
--检查等待事件,已恢复正常
set lines 180 pages 999
column event format a60
select event, count(*) as amount
from v$session
where event is not null
and wait_class 'Idle'
group by event
order by count(*) desc;
4.5、启动监听
GI 单实例:crsctl start res $ORACLE_SID.lsnr
RAC 环境:srvctl start listener -l $ORACLE_SID
VCS 单实例:lsnrctl start $ORACLE_SID
4.6、启动 crontab
crontab .cron_file
4.7、前台验证连通性,并通知运营检查应用
5、重启数据库方案(10分钟)
5.1、前置检查步骤(1分钟)
a.检查undo占用
--检查是否有活跃会话占用大于50M的undo
set linesize 180 pagesize 999
select inst_id,sid,serial#,xidusn,undo_size_m,sess_status,status,username,sql_id,prev_sql_id,machine,start_time,logon_time,related_rows,sql_text
from (select t.xidusn,s.status sess_status,t.status,s.inst_id,s.sid,s.sql_id,s.prev_sql_id,s.serial#,s.username,s.machine,t.start_time,s.logon_time,t.used_urec related_rows, round(t.used_ublk * block_size / 1024 / 1024, 0) undo_size_m,q.sql_text
from gv$session s,
gv$transaction t,
dba_tablespaces dt,
gv$system_parameter p,
gv$sql q
where q.sql_id(+) = s.sql_id and upper(p.name) = 'UNDO_TABLESPACE' and dt.tablespace_name = p.value and t.inst_id = s.inst_id and p.inst_id = s.inst_id and s.saddr = t.ses_addr
and round(t.used_ublk * block_size / 1024 / 1024, 2) > 50
order by t.used_ublk desc) t where rownum < 20;
--检查正在回滚的事务占用undo大小
select a.inst_id,(select s.instance_name from gv$instance s where s.INST_ID= a.INST_ID ) instance_name,usn,slt,state,pid,
a.undoblockstotal ,a.undoblocksdone "Done",a.undoblockstotal - a.undoblocksdone "ToDo",to_char(sysdate, 'yyyy-mm-ddhh24:mi:ss')
"Now",round((a.undoblockstotal -a.undoblocksdone)/(a.undoblocksdone / a.cputime)/60,2) "Need_time_min",round(a.undoblockstotal * 8192 / 1024 / 1024 / 1024,2) ||' G' "Undo_used_gb",decode(cputime,0,'unknown',to_char(sysdate +(((undoblockstotal -undoblocksdone) /(undoblocksdone / cputime)) / 86400),'yyyy-mm-ddhh24:mi:ss')) "Estimatedtime to complete"
from gv$fast_start_transactions a
where state ='RECOVERING';
b.检查MTTR时间
set linesize 180
select recovery_estimated_ios,
actual_redo_blks,
target_redo_blks,
log_file_size_redo_blks,
target_mttr,
estimated_mttr
from v$instance_recovery;
说明: 如果没有大undo占用并且$instance_recovery.estimated_mttr小于600秒,可以立即关闭数据库,否则建议延迟关闭。
5.2、关闭数据库(不分架构)(6分钟)
5.2.1、正常关闭数据库(5分钟)
show parameter job_queue_processes
show parameter aq_tm_processes
alter system set job_queue_processes=0 scope=both;
alter system set aq_tm_processes=0 scope=both;
alter system switch logfile; --停主库前多次switch logfile
alter system switch logfile;
alter system switch logfile;
alter system archive log current;
alter system checkpoint; --做一个检查点
shutdown immediate
说明:如果在5分钟后,关闭还未结束,alert.log中没有相关的关闭信息,执行步骤5.2.2
5.2.2、强制关闭数据库(1分钟)(风险较大,请升级部门长确认方案)
shutdown abort
5.3、启动数据库
5.3.1、如果前面是正常停库
startup
5.3.2、如果前面是非正常停库
create pfile=’/tmp/inittemp.ora’ from spfile;
然后修改新生成的 /tmp/inittemp.ora 参数文件中的设置
设置或修改 fast_start_parallel_rollback=high
启动数据库
startup pfile=’/tmp/inittemp.ora’
使用原参数文件重启数据库
shutdown immediate
startup
5.4、后台登陆数据库会话及检查等待事件,前台验证连通性,并通知运营检查应用
--检查连接数,使用率已下降
select 'session:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$session) a
where s.NAME = 'sessions'
union
select 'process:' || round(a.cnt / value * 100) || '%'
from v$parameter s, (select count(*) as cnt from v$process) a
where s.NAME = 'processes';
--检查等待事件,已恢复正常
set lines 180 pages 999
column event format a60
select event, count(*) as amount
from v$session
where event is not null
and wait_class 'Idle'
group by event
order by count(*) desc;
如果前面有停监听记得启动监听
GI 单实例:crsctl start res $ORACLE_SID.lsnr
RAC 环境:srvctl start listener -l $ORACLE_SID
VCS 单实例:lsnrctl start $ORACLE_SID