其他4

2023年 9月 2日 88.2k 0

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

其他4-1

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论