数据容灾解决方案之data guard

      前一阵子被客户要求提供一份备份策略,主要包含数据库、应用层面的,其目的很明确就是防止将来的生产环境发生意外而提前制定一系列的系统容灾方案。制定这套方案一般是在系统建设初期,设备采购阶段。说起来可笑,这眼看二期都要竣工,客户才要求我们提供这套方案,不知道是我们工作失职,还是客户够沉得住气,这里也不多说了,先把数据库的备份策略贴出来,有不足的地方还请大家多多指教.

      提到ORACLE数据库容灾,我以往接触到都是逻辑备份,通过exp命令导出,利用crontab 制定备份周期,最终通过人工将DMP拷贝到离线设备中。个人觉得那个太落后,恢复时间太过漫长。一旦数据文件损坏,还需要重新建库,这对运营支撑系统来说,损失是惨重的,当然dbstar是个例外。 ORACLE的备份功能很强大、很灵活,客户既然花了那么多钱购买service,一定要充分利用。

      ORACLE10G推出以后,DATA GUARD 让人眼前一亮,Oracle Data Guard 是管理、监控和自动化软件的基础架构,它创建、维护和监控一个或多个备用数据库,以保护企业数据结构不受故障、灾难、错误和崩溃的影响,所以我决定利用这个利器来制定数据库级别容灾策略。

     

关于DG的介绍请查看官网的文档,这里废话不多说,直接贴出我的配置步骤:

一、主机与数据库的配置

DBSTAR主库

10.1.252.153

db_name = orcl

db_unique_name/ORACLE_SID = primary

DBSTAR物理备库

10.1.251.133

db_name = orcl    --需和主库一致

db_unique_name/ORACLE_SID = standby

二、数据库监听的配置

DBSTAR主库

SID_LIST_LISTENER =

  (SID_LIST =

   (SID_DESC =

      (GLOBAL_DBNAME = primary)

      (ORACLE_HOME = /home/oracle/oracle/product/10.2.0/db_1)

      (SID_NAME = orcl)

    )

   (SID_DESC =

      (GLOBAL_DBNAME = primary_DGMGRL)

      (ORACLE_HOME = /home/oracle/oracle/product/10.2.0/db_1

      (SID_NAME = orcl)

    )

  )

LISTENER =

  (DESCRIPTION_LIST =

    (DESCRIPTION =

      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))

      (ADDRESS = (PROTOCOL = TCP)(HOST = test_host1)(PORT = 1521))

    )

  )

DBSTAR物理备库

SID_LIST_LISTENER =

(SID_LIST =

(SID_DESC =

      (GLOBAL_DBNAME = standby)

      (ORACLE_HOME = /home/oracle/oracle/product/10.2.0/db_1)

      (SID_NAME = orcl)

    )

   (SID_DESC =

      (GLOBAL_DBNAME = standby_DGMGRL)

      (ORACLE_HOME = /home/oracle/oracle/product/10.2.0/db_1)

      (SID_NAME = orcl)

    )

  ) 

LISTENER =

  (DESCRIPTION_LIST =

    (DESCRIPTION =

      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))

      (ADDRESS = (PROTOCOL = TCP)(HOST = test_host2)(PORT = 1521))

    )

  )

三、将主、备库设置为归档模式

archive log list;

shutdown immediate;

startup mount;

alter database archivelog;

alter database open

SQL>alter system set LOG_ARCHIVE_DEST_1='LOCATION=/home/oracle/archive/$db_unique_name';

四、修改主库的初始化文件

在$ORACLE_HOME/DBS/init$ORACLE_SID添加下面内容

#将主备库的DB_UNIQUE_NAME添加到DATA GUARD中,如果缺少这个参数,可能会导致归档路径被禁用。

log_archive_config='DG_CONFIG=(primary,standby)'

#设置主库默认日志归档的路径

log_archive_dest_1='LOCATION=/home/oracle/oradata/archive/primary VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=primary'

log_archive_dest_state_1='ENABLE'

五、通过RMAN将主库复制到备库上一份

$ rman target /

RMAN> backup full database format '/home/oracle/backup/dbfull_%T_%s_%p.bak';

RMAN> exit

六、通过主库给备库创建初始化文件initstandby.ora

$ sqlplus '/as sysdba'

SQL> alter system archive log current

SQL> alter database create standby controlfile as '/home/oracle/backup/control01.ctl' reuse;

SQL> exit

为安全起见,控制文件一般设置三份:

$ cp /home/oracle/backup/control01.ctl /home/oracle/backup/control02.ctl

$ cp /home/oracle/backup/control01.ctl /home/oracle/backup/control03.ctl

注意:建备库控制文件前产生的归档文件后续不会传送给备库,这是正常的。

七、拷贝上面生成的文件backup_*.bak、control0*.ctl、init*.ora到备机对应目录下

注意:备机上RAMN对应的备份目录与主机一定要相同,否则无法恢复

八、在备库上建spfile并启动备库

SQL> create spfile from pfile='/home/oracle/backup/initstandby.ora ';

SQL> startup nomount;

SQL> alter database mount standby database;

SQL> exit 

九、备库做rman恢复

$ rman target /

RMAN> restore database

RMAN> exit

十、启动监听并确保在主备库间能互相tnsping通

$ lsnrctl start

$ tnsping standby

$ lsnrctl status (确保备库监听standby实例成功) 

主库(primary):

$ tnsping primary

$ tnsping standby

$ lsnrctl status (确保主库监听primary实例成功)

十一、主库增加归档目的地参数并归档测试

$ sqlplus '/as sysdba'

SQL> alter system set log_archive_dest_2='SERVICE=standby LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=standby' scope=both;

SQL> alter system set log_archive_dest_state_2='ENABLE' scope=both;

SQL> alter system archive log current; --这时主库生成的归档日志就会同步到备库上

十二、将备库激活为recover 状态

SQL> alter database mount standby database;

SQL> alter database recover managed standby database disconnect from session;  (standby)

这样一来数据库就可以根据归档日志来做同步了。

十三、将备库修改为只读状态

SQL> alter database recover managed standby database cancel;(standby)

SQL> alter database open readly

此时数据库以只读模式打开,可以对数据进行查询操作(standby 数据库不能做修改删除等其它类型的操作)

当遇到下面这个错误时

ERROR at line 1:

ORA-16004: backup database requires recovery

ORA-01152: file 1 was not restored from a sufficiently old backup

ORA-01110: data file 1: '/home/oracle/oradata/orcl/system01.dbf'

请将备份再次激活为recover 状态,然后在主库里执行一次日志切换,生成备份后最后一次的归档日志。

SQL> alter database recover managed standby database disconnect from session;  --主库

SQL> alter system switch logfile; --主库

SQL> alter database open; --备库

因为当你做备份整个数据库时,主库的归档日志和控制文件任然会发生改变,其SCN号与数据文件不一致,所以备库需要根据主库新生成的日志进行恢复。

十三、角色切换(主备库切换)

这里我们使用DGMGRL管理 Data Guard broker,当主库发生故障时,利用dgmgrl进行主备库切换,下面是角色的转换的几种情况和注意事项:

主数据库和备用数据库角色的转换

转换

–  计划的角色转换

–  无需将数据库重新实例化

–  用于维护操作系统和硬件

故障切换

–  主数据库出现意外故障(例如灾难)

–  在failover之前一定要将数据库设置成闪回模式,否则原主库在做了灾难恢复之后如果想再次作为备库使用,只能重建。

利用简单的 SQL / GUI 界面进行初始化

Data Guard 使涉及到的过程自动化.

十四、归档日志的清理

    DG的工作机制就是通过主库向备库传输归档日志,由备份数据库做apply操作完成的。

它不单在DG中使用,在任何一种灾难的恢复过程中都是必不可少的,由此可见归档日志的重要性。不过每天产生的归档文件,长年累月积累下来会占用系统很大的空间,尤其是分布式数据库(BOSS)对数据库的操作频度比较大,如果不及时清理磁盘空间达到饱和以后,就会发生严重的后果。主库和备库都需要定期的删除日志文件,备库可以根据apply的状态为=YES直接删除,但主库在只有做了备份以后才可以做删除,否则如果发生数据文件损坏的时候,丢失了任何一个时间点的日志文件,都是无法做数据库恢复的。

#!/bin/bash

##################################################################################################################

#

# This script is to delete the arch logs for the standby database after it has applied the logs to the instance.

#

##################################################################################################################

source /home/oracle/.bash_profile

 

#####################

usage()

{ #usage

echo " USAGE: `basename $0` $retention"

exit 2

ArgNum=1

if [ ! $# -eq $ArgNum ]; then

echo " "

echo " Incorrect parameter"

usage

fi

retention=$1

script=`basename $0` 

dir=/home/oracle/backup

tmpf=$dir/.$script.tmp

# get archived log list for standby database

function GetLogListForStandby

{

echo "congqing"

sqlplus -S /nolog <$tmpf

connect / as sysdba

set head off

set feedback off

set pages 0

select name from(

select name,sequence#,row_number() over(partition by a.sequence# order by name) rn,

count(decode(applied,'YES',1,null)) over (partition by a.sequence#) cn #检查是否做了apply

from v/$archived_log a

where completion_time

and a.resetlogs_id in (

select i.resetlogs_id from v/$database_incarnation i where status = 'CURRENT')

)

where rn=1 and cn=1

order by sequence#;

exit

EOF

return

}

function GetDBRole

{

sqlplus -S /nolog <

connect / as sysdba

set head off

set feedback off

set pages 0

select controlfile_type from v/$database;

exit

EOF

return

}

# get archived log list for primary database

function GetLogListForPrimary

{

sqlplus -S /nolog < $tmpf

connect / as sysdba

set head off

set feedback off

set pages 0

select name from(

select name,sequence#,row_number() over(partition by a.sequence# order by name) rn,

sum(backup_count) over(partition by a.sequence# ) bk_cnt, #检查是否做过备份(可选)

count(decode(applied,'YES',1,null)) over (partition by a.sequence#) cn #检查是否做了apply

from v/$archived_log a where completion_time

and a.resetlogs_id in (

select i.resetlogs_id from v/$database_incarnation i where status = 'CURRENT')

)

where rn=1 and cn=1 and bk_cnt>0

order by sequence#;

exit

EOF

return

}

function GetDBRole

{

sqlplus -S /nolog <

connect / as sysdba

set head off

set feedback off

set pages 0

select controlfile_type from v/$database;

exit

EOF

return

}

# check database role

DBROLE=`GetDBRole`

NUM=0

if [ $DBROLE = "CURRENT" ];then

echo "It's a primary database ......"

# get archived log list for primary

GetLogListForPrimary

elif [ $DBROLE = "STANDBY" ];then

echo "It's a standby database ......"

# get archived log list for standby

GetLogListForStandby

fi

echo "deleting archived log files ......" 

if [ -n $tmpf ]; then

for ARCH in `cat $tmpf`;do

if [ -f $ARCH ];then

NUM=`expr $NUM + 1`

rm -f $ARCH

fi

done

fi

rm -f $tmpf

echo "finished deleting $NUM files"

 

设置定时任务crontab 定期执行脚本,清除归档日志

crontab –u oracle –e

* * */1 * * /home/oracle/backup/delArchLogs.sh 1

每天执行一次

 

待续....

你可能感兴趣的:(系统容灾)