大家好,这里是 Lucifer三思而后行,专注于提升数据库运维效率。
目录
前言
最近有客户的 shareplex 因为一些稀奇古怪的原因又挂了,由于邮件告警问题,没有及时通知到,并且归档已经被删除,备份也追溯不回丢失的归档日志。
经过与客户确认repo库没有历史数据需保留,直接重建修复!
准备
确认以下条件均已具备:
- 有可用备份;
- 磁盘空间足够;
- 由于使用 networker 备份,需要提前安装备份恢复所需客户端;
本次重建目标端使用 rman 进行全库恢复。
重建过程
确认数据库大小
select sum(bytes/1024/1024/1024) from dba_segments;
select sum(bytes/1024/1024/1024) from dba_data_files;
复制
确认目标端磁盘空间足够!
确认备份可用
--查询备份
set line222
set pagesize100
col status for a10
col input_type for a20
col INPUT_BYTES_DISPLAY for a10
col OUTPUT_BYTES_DISPLAY for a10
col TIME_TAKEN_DISPLAY for a10
select input_type,
status,
to_char(start_time,
'yyyy-mm-dd hh24:mi:ss'),
to_char(end_time,
'yyyy-mm-dd hh24:mi:ss'),
input_bytes_display,
output_bytes_display,
time_taken_display,
COMPRESSION_RATIO
from v$rman_backup_job_details
where start_time > date '2021-08-10'
order by 3 desc;
复制
list backup of controlfile;
复制
ctrl_mesdbtj_65271_1_1081487814
确认最新的有效备份,记录控制文件。
安装 networker 客户端
安装包上传目标端安装
lgtoclnt-9.2.1.4-1.x86_64.rpm lgtonmda-9.2.1.4-1.x86_64.rpm
复制
建议使用 yum install
进行安装,防止依赖包缺失,前提是 yum 源已配置。
按顺序安装:
yum install -y lgtoclnt-9.2.1.4-1.x86_64.rpm systemctl start networker systemctl start networker yum install -y lgtonmda-9.2.1.4-1.x86_64.rpm
复制
lgtoclnt
安装完成后,确保服务正常运行,再安装 lgtonmda
。
配置解析
必须将目标端和源端,networker 服务端的ip和主机名解析全部写入 /etc/hosts 文件。
目标端链接 NMO 库文件
cd $ORACLE_HOME/lib
ln –s /usr/lib/libnsrora.so libobk.so
复制
至此,networker 目标端已安装完成。
清理 shareplex 旧环境
源端和目标端关闭 shareplex
sp_ctrl shutdown
复制
源端和目标端执行清理脚本
/quest/bin/ora_cleansp splex2300/splex2300 /data/quest/bin/ora_cleansp splex2300/splex2300
复制
源端和目标端重新开启 shareplex 环境
sp_cop -u2300&
复制
本文 shareplex 使用端口为 2300,读者需根据实际情况更换,如 2400、2500 等。
目标端停止 post 进程
stop post
复制
最后全部恢复完毕之后再开启。
开始 rman 恢复
确保目标端数据库已开启到 nomount 状态。
恢复控制文件
连接 rman 客户端后执行恢复控制文件:
run {
allocate channel c1 type 'SBT_TAPE';
send 'NSR_ENV=(NSR_SERVER=这里填写 networker 服务端主机名,NSR_CLIENT=这里填写源端备份主机名)';
restore controlfile from '这里填写最新备份控制文件名称';
release channel c1;
}
``
恢复完之后开启目标端数据库到 mount 状态。
### 恢复数据
由于数据库大概有 1-2 T 的大小,恢复时间很长,因此建议将恢复脚本放在后台进行执行,脚本如下:
```bash
#!/bin/bash
source ~/.bash_profile
backtime=`date +"20%y%m%d%H%M%S"`
rman target / log=/home/oracle/rman_repo_$backtime.log<<EOF
run {
allocate channel c1 type 'SBT_TAPE';
allocate channel c2 type 'SBT_TAPE';
allocate channel c3 type 'SBT_TAPE';
allocate channel c4 type 'SBT_TAPE';
send 'NSR_ENV=(NSR_SERVER=这里填写 networker 服务端主机名,NSR_CLIENT=这里填写源端备份主机名)';
set newname for database to '/data/mesdb/%b';
restore database;
switch datafile all;
recover database;
release channel c1;
release channel c2;
release channel c3;
release channel c4;
}
exit;
EOF
复制
执行 sh rman_sp.sh &
进行后台恢复。
📢 注意: 通道根据实际情况进行修改,由于源端是 rac 环境,目标端是单机环境,因此数据文件路径需要 set newname
进行转换,最后执行初次 recover database
。
备份恢复完之后,由于缺少归档,所以需要追归档。
追归档日志
由于备份时间与当前时间存在较大时差,在获取当前源端的 scn 进行 recover 时,必然需要追大量的归档日志文件,为了减少 shareplex 积压,因此提前追归档日志到当前时间。
源端备份归档日志到当前最新:
backup archivelog from sequence 71457 until sequence 71986 thread 1; backup archivelog from sequence 65247 until sequence 65780 thread 2;
复制
备份成功后拷贝至目标端,注册目录后执行 recover
:
catalog start with '/data/archivelog/';
recover database;
复制
追完归档之后,激活源端 shareplex 的 config 文件。
激活源端 config 配置文件
list config activate config ORA_config_20210825 nolock show config
复制
激活成功后,检查源端数据库中是否存在 长事务。
select start_time from gv$transaction;
复制
如果有长事务,可以确实是否可以杀掉,杀掉后才能继续操作。
根据以下 SQL 可以获取到事务的详细情况:
set linesize 260 pagesize 10000
column sess format a21 heading "SESSION"
column program format a18
column clnt_pid format a8
column machine format a25
column username format a12
column osuser format a13
column event format a32
column waitsec format 999999
column start_time format a18
column sql_id format a15
column clnt_user format a10
column svr_ospid format a10
ALTER SESSION SET NLS_DATE_FORMAT = 'yyyy/mm/dd hh24:mi:ss';
set feedback off
set echo off
set head off
select chr(9) from dual;
select 'Waiting Transactions'||chr(10)||'====================' from dual;
set head on
select /*+ rule */
lpad(nvl(s.username,' '),8)||'('||s.sid||','||s.serial#||')' as sess,
p.spid as svr_ospid,
nvl(osuser,' ') as clnt_user,
s.process as clnt_pid,
substr((case instr(s.PROGRAM, '@')
when 0 then
s.program
else
case instr(s.PROGRAM, '(TNS V1-V3)')
when 0 then
substr(s.program, 1, instr(s.PROGRAM, '@') - 1) || substr(s.program, instr(s.PROGRAM, '(') - 1)
else
substr(s.program, 1, instr(s.PROGRAM, '@') - 1)
end
end),
1, 18) as program,
(case
when length(s.MACHINE) > 8 then substr(s.machine,1,8)||'~'
else s.machine
end
) || '('||nvl(s.client_info, 'Unknown IP')||')' as machine, s.sql_id,
substr(s.event, 1, 32) as event,
s.seconds_in_wait as waitsec
from v$transaction t,v$session s,v$process p
where t.ses_addr=s.saddr and s.paddr=p.addr
order by s.seconds_in_wait, s.program, s.machine;
复制
可以通过 SESSION
字段来杀掉事务:
alter system kill session '1841,44697';
复制
如果杀不掉,则使用 svr_ospid
系统层进行 kill:
kill -9 27353
复制
确认没有长事务后,继续下一步操作。
源端获取 scn 号
col current_scn format 9999999999999999 select current_scn from v$database;
复制
记录获取到的 SCN 号:72863106548
。
目标端 rman 恢复至指定 scn
recover database until scn 72863106548;
复制
因为源端一直在运行,激活期间到SCN号必然会有新的归档产生,提示缺少归档日志,因此需要去源端拷贝缺少的归档日志,再次进行 recover。
目标端开启 resetlogs 状态
alter database open resetlogs;
复制
确认 recover 完成恢复之后,基本恢复结束,可以开启目标端到 resetlogs 状态。
rman 恢复后收尾
目标端 reconcile 至指定SCN号
reconcile queue q1 for o.mesdb2-o.mesdb scn 72863106548
reconcile queue q2 for o.mesdb2-o.mesdb scn 72863106548
reconcile queue q3 for o.mesdb2-o.mesdb scn 72863106548
reconcile queue q4 for o.mesdb2-o.mesdb scn 72863106548
reconcile queue q5 for o.mesdb2-o.mesdb scn 72863106548
复制
非必须操作,如果出现 hang
住的情况,需要在源端 shareplex 执行 flush 操作疏通通道:
flush o.mesdb2 to mes-repo queue q1 flush o.mesdb2 to mes-repo queue q2 flush o.mesdb2 to mes-repo queue q3 flush o.mesdb2 to mes-repo queue q4 flush o.mesdb2 to mes-repo queue q5
复制
📢 注意: 源端执行过 flush 的通道,目标端 start post
之后需要再次执行 start post queue 指定队列名
,否则无法开启 post。
目标端运行 cleanup.sql 来清空内部表信息
cd /data/quest/bin/
sqlplus splex用户账号/splex账户密码
@cleanup.sql
复制
该步骤用于清理源端 splex 用户相关数据。
目标端禁用所有 trigger
SELECT 'alter trigger ' || owner || '.' || trigger_name || ' disable;'
from dba_triggers
where owner in (需要同步的用户);
复制
将输出结果复制执行即可!
目标端禁用所有约束
SELECT 'alter table '||owner||'.'||table_name||' disable constraint '||constraint_name||';' from dba_constraints
where constraint_type='R' and owner in (需要同步的用户);
复制
将输出结果复制执行即可!
禁用job
alter system set job_queue_processes=0;
复制
确保 job 任务不会运行!
目标端开启 post 进程
sp_ctrl start post
复制
确保所有队列均已处于正常 running 状态。
由于目标端执行 reconcile 时 2,4 队列 hang
住,因此需要单独 start post queue 指定队列名
来开启:
start post queue q2 start post queue q4
复制
状态已全部正常 running。
重建后检查
qstatus
show post queue q2
show log reverse
复制
通过命令查看同步是否正常,以及同步速度是否正常。再次确认邮件告警是否恢复正常。
写在最后
shareplex 重建恢复的流程还算复杂,因此需要做好必备的告警措施,防止遇到停止导致问题发生,无法及时补救的情况。
分享两个告警脚本:
1、监控 shareplex 进程是否正常运行:
#!/bin/bash
if [ -f ~/.bash_profile ];
then
. ~/.bash_profile
fi
count=`ps -ef|grep sp_cop|wc -l`
if [ "${count}" -ne 2 ];
then
ps -ef|grep sp_cop > /tmp/sp_cop.log
mail -s "Shareplex sp_cop process shutdown" 邮箱地址 < /tmp/sp_cop.log
fi
复制
2、监控 shareplex 队列是否存在异常:
#!/bin/bash
if [ -f ~/.bash_profile ];
then
. ~/.bash_profile
fi
rm -rf /data/quest/error.log
echo "show "|sp_ctrl|grep "Idle" >> /data/quest/error.log
echo "show "|sp_ctrl|grep "Stopped" >> /data/quest/error.log
# -s 文件大小非0时为真
if [ ! -s /data/quest/error.log ]
then
rm -rf /data/quest/error.log #文件大小为0 删除
fi
if [ -s /data/quest/error.log ]
then
mail -s "Shareplex error" 邮箱地址 < /data/quest/error.log
fi
复制
📢 如有问题,请及时指正,谢谢!
往期精彩文章
Oracle 一键巡检自动生成 Word 报告
Oracle 一键安装合集
Oracle一键安装脚本的 21 个疑问与解答
Oracle一键巡检脚本的 21 个疑问与解答
全网首发:Oracle 23ai 一键安装脚本(非 RPM)
Oracle 19C 最新 RU 补丁 19.24 ,一键安装!
Oracle Linux 7.9 一键安装 Oracle 19C
RedHat 9.4(aarch64) 一键安装 Oracle 19C
openEuler 22.03 LTS SP4 一键安装 Oracle 19C RAC
RHEL 7.9 一键安装 Oracle 19C 19.23 RAC
Oracle DataGuard GAP 修复手册
优化 Oracle:最佳实践与开发规范
DBA 必备:Linux 软件源配置全攻略
Linux 一键配置时钟同步全攻略
感谢您的阅读,这里是 Lucifer三思而后行,欢迎点赞+关注,我会持续分享数据库知识、运维技巧。