分类: Oracle
2013-01-14 10:26:28
最近做了10g和11g的物理备库配置实验,发现 Data Guard 其实很容易,但是缺少好文档。我是参考官方文档做的实验,觉得它写的不是很清楚的。
Google 出来两个pdf文档,读了觉得比官方文档强很多。翻译下,也许会对某些朋友有用。翻译的同时我也好更熟悉下这两个文档。好久没翻译过英文了,可以顺便练练手。
原文档下载地址(墙外):
Data Guard 是 Oracle 数据库的一个功能,能够提供数据库的冗余。冗余是通过创建一个备用(物理复制)数据库实现,备库最好是在不同的地理位置或者在不同的磁盘上。备库通过应用主库上的变化来保持数据同步。备库可以使用重做日志应用(物理备库)或SQL应用同步(逻辑备库)。
本文旨在说明 Data Guard 的配置并不复杂,不需要特殊的技能或者培训才能学会搭建。它将快速展示给读者搭建一个物理备库的过程。我的目标是,即使你第一次接触 Data Guard,刚考虑要使用它或担心它会不会很难配置,本文将帮助你快速搭建起一个正常运行起来的物理备库。
为什么使用 Data Guard每种 Oracle 高可用性工具都有其目的。使用 Data Guard 的理由有:
在写完本文后,我使用 DBCA 创建了一个新数据库 JED,然后重新运行了文中的配置步骤,确认其对一个基本的 Oracle 11g 数据库适用。主库叫 JED,运行在一台叫 dev-db1的服务器上。备库叫JED2,运行在一台叫 dev-db2 的服务器上。
不需要提的基本前提有一些任何生产库都应该有的基本的设置。其中一个就是归档模式。对于生产库,这应该是一个明显的必须配置。如果你的生产库没有适用归档模式,你要么需要马上开始读点书,要么你得有一个非常非常好的理由。我不大确定谁真能找出一个理由,但任何准则都有例外。
如何修改你的数据库为归档模式:
SQL> shutdown immediate SQL> startup mount SQL> alter database archivelog; SQL> alter database open; SQL> archive log list; 主库准备首先,备库要成为主库的完全相同的复制,它必须接收来自主库的重做日志。Oracle 数据库中,一个用户可以用指定某操作不产生日志(比如使用 NOLOGGING 语句)。对于备库来说,这是个问题。你必须确认用户无法指示数据库不产生重做日志,这需要启用数据库的强制日志功能。启用方法如下:
SQL> alter database force logging; SQL> select name, force_logging from v$database;你应该看到 force_logging 列为 YES。
其次,你要确认当主库添加或删除数据文件时,这些文件也会在备库添加或删除。启用此功能的方法如下:
SQL> alter system set standby_file_management = 'AUTO';再次,我们要确认书库有备用日志文件(Standby Log Files)。备库使用备用日志文件来来保存从主库接收到的重做日志。主库上也建立备用日志文件有两个原因,一是主库可能转换成备库,备库需要备用日志,二是如果主库建了备用日志,备库会自动建。备用日志应该跟在线日志一样大,组数应该至少跟在线日志一样多,或者更多。我喜欢给备用日志一个跟在线日志不同范围的编号,比如在线日志组是1到6,备用日志就是11到16。创建备用日志的方法如下:
SQL> alter database add standby logfile group 11 ('/oradata/JED/g11m01.sdo','/oradata/JED/g11m02.sdo') size 50M;如果你不是使用 SSL 做重做日志传输验证(一般来说不会),那么你需要使用密码文件做验证。你必须创建密码文件,并且设置参数 REMOTE_LOGIN_PASSWORDFILE 为 EXCLUSIVE 或 SHARED。一般数据库默认就有密码文件,并且此参数默认为 EXECUSIVE。先检查下这两项,如果不是默认,设置方法如下:
SQL> alter system set remote_login_passwordfile=exclusive scope=spfile; OS> orapwd password=最后,检查数据库的 db_unique_name 参数是否设置。如果没有,使用 alter system 进行设置:
SQL> show paramter db_unique_name; SQL> alter system set db_unique_name=some_name scope=spfile; 闪回数据库我强烈建议开启数据库闪回功能。闪回允许你将数据库还原到以前的某一时间点。当发生故障转移时,这个功能非常有用,它能让你将老的主库闪回到故障前,然后将其转换为备库。如果没有启用闪回功能,你就必须重建备库,意味着要再复制一次数据文件。除了这个好处,闪回还能在某些情况下让你避免从备份恢复数据。
启用闪回功能,必须先配置快速恢复区(Flash/Fast Recovery Area). 方法如下:
SQL> alter system set db_recovery_file_dest='&快速恢复区目录或ASM磁盘组名'; SQL> alter system set db_recovery_file_dest_size=400G;配置好快速恢复区后,就可以启用闪回日志功能:
SQL> alter database flashback on; SQL> select flashback_on from v$database;FLASHBACK_ON 这列的值应该是 YES。如果你碰到 ORA-01153 报错,那一定是在备库进行此操作。你需要先取消重做日志应用,启用闪回日志,然后重新启用日志应用。
在主库启用闪回日志,不会同步备库也启用。你必须手动在主库和备库上均启用闪回日志。如果不启用闪回日志,当出现故障转移时,你将需要完全重新开始创建一个备库。
SQL*NET 配置在创建备库前,要确认两台服务器的数据库之间能通信,如果我们要用 RMAN 的 duplicate from active database 命令创建备库的话。我们需要配置监听和 TNS 名。你可以手动配置,也可以使用网络配置工具(netca)。我更喜欢手动配置,因为我比较老派,并且这些配置文件又不复杂,
首先需要配置主备库的监听。虽然数据库会自动注册监听,但如果要使用 RMAN 的 duplicate 命令创建备库,备库必须首先处于 NOMOUNT 状态。在 NOMOUNT 状态下,数据库实例不会自动注册监听,你必须配置静态监听。另外必须要注意的一点是,NOMOUNT 状态下的数据库必须使用专用模式(dedicated server)连接。
两台服务器上的 TNS 名字文件必须配置好,让主备库能用 LOG_ARCHIVE_DEST_N 和 FAL_SERVER 参数(稍后会介绍这些参数)中的服务名(Service Names)找到对方。具体配置应类似下例。
主库(dev-db1)的监听配置:
SID_LIST_LISTENER= (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = JED) (ORACLE_HOME = /oracle/product/11.2.0) (SID_NAME = JED) ) )备库(dev-db2)的的监听配置:
SID_LIST_LISTENER= (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = JED2) (ORACLE_HOME = /oracle/product/11.2.0) (SID_NAME = JED2) ) )主库的 TNS 名字文件配置:
JED2 = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dev-db2)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = JED2) ) )备库的 TNS 名字文件配置:
JED = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dev-db1)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = JED) ) ) 重做日志传输配置现在主备库之间依旧可以互相通信了,下一步是配置归档位置和重做日志传输。我们将先在主库上进行配置,然后等备库创建好后,修改备库的配置。
配置归档位置:
SQL> alter system set log_archive_dest_1 = 'location=use_db_recovery_file_dest valid_for=(all_logfiles, all_roles) db_unique_name=JED';这个命令指定快速恢复区作为归档位置,此归档位置用于在所有数据库角色下归档所有的日志文件。官方文档里说使用 valid_for=(online_logfiles, all_roles),这将导致备库无法归档备用日志文件,因为它们不是在线日志。但如果使用 all_logfiles 选项,主备库将都能归档在线以及备用日志。如果你想在备库进行备份,并同时备份归档日志的话,必须使用 all_logfiles。
然后配置重做日志传输到备库:
SQL> alter system set log_archive_dest_2 = 'service=JED2 async valid_for=(online_logfile,primary_role) db_unique_name=JED2';这条语句说,如果这是主库,就使用服务名 JED2 传输在线日志,目标库名叫 JED2。
要注意STANDBY_ARCHIVE_DEST 参数不需要,已经被官方弃用。当调试时,不少人好心建议我设置此参数,但设置此参数后启动数据库,只会报 ORA-32004: obsolete or deprecated parameter(s) specified for RDBMS instance 错。
另一个要设置的参数是 FAL_SERVER。这个参数指定当日志传输出现问题时,备库到哪里去找缺少的归档日志。它用在备库接收的到的重做日志间有缺口的时候。这种情况会发生在日志传输出现中断时,比如你需要对备库进行维护操作。在备库维护期间,没有日志传输过来,这时缺口就出现了。设置了这个参数,备库就会主动去寻找那些缺少的日志,并要求主库进行传输。
SQL> alter system set fal_server = 'JED2';注意 FAL_CLIENT 参数在11g里已经弃用。
然后我们要让主库知道 Data Guard 配置里的另外一个库的名字:
SQL> alter system set log_archive_config = 'dg_config=(JED,JED2)';这一步做完后,我们就可以准备好备库的环境,并开始创建备库了。
备库环境准备现在开始准备备库环境。有很多种方法来执行这些步骤。我这里写的是我觉得最适合我的方法。你应该实验多种方法,看哪种比较适合你。
首先,我们要为备库创建密码文件和参数文件(spfile)。密码文件可以直接复制过去,只需要改下名字就行。比如,主库上的密码文件是 $ORACLE_HOME/dbs/orapwJED。我们把它复制到备库服务器的相同位置,用备库的 SID 取代主库,修改其名字为 orapwJED2。
为了创建备库 spfile,先创建一个启动参数文件(pfile):
SQL> create pfile from spfile;我想介绍一个看起来挺不错新功能,使用 RMAN 创建备库 SPFILE。我不使用这个功能的理由是:
我发现复制 pfile 过去更容易(你甚至可以直接粘贴复制),只要改下名字,然后改几个里面的参数就行。这很容易,你也可以在手动修改和调试的过程中学到很多。我发现手动改比用 RMAN 的SPFILE创建功能更快。
创建好了主库的 pfile 后,将其复制到备库服务器的相同位置,使用备库的 SID 修改其名字。你需要对 pfile 做如下修改:
然后在备库服务器上创建所需目录结构和修改相关文件。至少需要修改如下创建目录和文件:
现在可以准备启动备库实例来创建数据库了。在启动过程中创建一个 spfile。
SQL> startup nomount pfile=initJED2.ora SQL> create spfile from pfile; SQL> shutdown SQL> startup nomount SQL> show parameter spfile SQL> exitshow parameter spfile 显示 spfile 的位置,这时备库处于 NOMOUNT 状态。
备库创建就像之前的步骤一样,创建数据库这一步也可以有多种方法。在11g中,我将使用 RMAN 的复制功能,因为它很容易。在上一步里,我们复制了密码文件和参数文件到备库服务器,修改好了参数文件,并创建了 spfile。这让使用 RMAN 复制功能更加容易,当然,你也可以跳过手工复制密码和参数文件这步,让 RMAN 使用 SPFILE,PARAMETER_VALUE_CONVERT 和 SET等命令帮你自动完成。
使用 RMAN 创建备库的命令非常简单。它指示 RMAN 直接复制当前活动的数据库(主库)到辅助数据库(备库)。这样你就不需要现将主库的备份复制到备库服务器上,再还原数据库。在今天的存储技术下,我们有更快更简单的方式复制数据库,但为了展示11g的这个新功能,并且这个功能又很简单,我喜欢尽可能使用它。
RMAN> connect target sys@JED RMAN> connect catalog在 11.2.0.2.0 版本后,你可以直接使用 connect target 连接辅助数据库,但如果不指定用户名和密码,在复制到备库时将报 invalid username/password 错。
当复制命令在执行时,我喜欢 tail 备库的告警日志文件,观察复制进行到了哪一步和查看是否有报错。注意,针对在线和备用日志文件报 ORA-27037: unable to obtain file status 错是正常的。
你也可以并行复制以提高性能。需要分派主库和备库多个通道后,再执行复制命令:
run { allocate channel chan1 type disk; allocate channel chan2 type disk; allocate channel chan3 type disk; allocate channel chan4 type disk; allocate auxiliary channel aux1 type disk; allocate auxiliary channel aux2 type disk; allocate auxiliary channel aux3 type disk; allocate auxiliary channel aux4 type disk; duplicate target database for standby from active database; }如果一切正常,你将看到 RMAN 报出类似如下信息:
Finished Duplicate Db at 07-MAY-10当备库复制完成后,我喜欢在备库启用闪回日志:
SQL> alter database flashback on; 启动重做日志应用启动或者停止重做日志应用非常容易。启动日志应用:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILEDISCONNECT FROM SESSION;
这个命令指示备库开始使用备用日志文件进行恢复。它也告诉备库命令完成后回到命令行界面。如果你想停止恢复:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL; 确认日志应用正常你要确认重做日志正在应用到备库。首先我们要确认主备库里的归档目的地配置都是有效的:
SQL> select DEST_ID, STATUS, DESTINATION, ERROR from V$ARCHIVE_DEST where DEST_ID<=2;目的地状态应该显示为 VALID。
然后确认重做日志是否真的被应用了,在主库执行:
SQL> select SEQUENCE#, FIRST_TIME, NEXT_TIME, APPLIED, ARCHIVED from V$ARCHIVED_LOG where name = 'JED2' order by FIRST_TIME;如果归档和日志应用均正常,APPLIED 和 ARCHIVED 列都应该是 YES。很多教程里都让这个查询以 SEQUENCE# 列排序,但我不推荐。如果以 SEQUENCE# 列排序,当你做了一次故障转移后,序列号会再从1开始,这时使用这个查询,你将不能在结果最后看到最新的记录。我曾经很奇怪为什么查不到新记录,其实是因为新记录不是出现在最后,我没看到。所以,这个查询都是以 FIRST_TIME 列排序。
如果你发现日志没有被应用,那可能是重做日志有了缺口,这种情况下备库无法进行日志应用。但如果你的 FAL_SERVER 参数设置正确,这应该不会有问题。你可以在主库上检查是否有重做日志缺口:
SQL> select STATUS, GAP_STATUS from V$ARCHIVE_DEST_STATUS where DEST_ID = 2;如果一切正常,应该返回 VALID 和 NO GAP。如果你想测试下 FAL_SERVER 这个参数是怎么工作的。可以先把备库关掉,然后在主库切换几次日志,等一会,启动备库,再切换一次日志。这样缺口很快就会出现。如果 FAL_SERVER 设置正常,缺少的重做日志会被传输过来并应用。
V$DATAGUARD_STATUS 视图对查找错误和了解发生了什么非常有用。可以在主备库上执行以下查询查看数据库状态:
SQL> select * from V$DATAGUARD_STATUS order by TIMESTAMP;有时候你手工想确认下数据真的同步了。一个更让人信服的方法是,直接查询备库,看新数据是否存在。你可以将备库打开为只读状态,首先取消日志应用,再执行如下命令:
SQL> ALTER DATABASE OPEN READ ONLY;这时你可以查询变化了的数据是否同步过来。11g已经支持活动备库,可以让数据库在只读状态下打开,同时启动日志应用。
总结现在你有一个配置好的 Data Guard,也就有了一个冗余的数据库。我不想留下主备转换、故障转移、重建库等不讲,这些主题将放到本文的第二部分。
我希望本文能帮助你更容易和更快速地创建你的 Data Guard 环境。
第二部分作者介绍
作者 Jed Walker 是科罗拉多 Centennial Comcast 媒体中心的数据操作经理(Manager of Databse Operation)。他从1997年开始做 Oracle 数据库相关工作,是9i, 10g和11g的OCP。
简介本文的第一部分讲解了如何配置一个基本的 Data Guard 环境。在第二部分里,我将介绍主备切换、故障转移(数据库和客户端)等其他主题。
回顾在本文第一部分中,我们配置了一个物理备库。在这第二部分中,我将介绍主备切换(Switchover),故障转移(Failover),客户端故障转移(Client Failover),使用闪回数据库重建库,活动数据卫士(Active Data Guard),还讨论了一点备份。
故障转移配置现在你已经配好了一个物理备库,你可能想试试主备切换(switchover),甚至故障转移(failover),但你先得确定客户端会跟着切换和转移。我们需要配置数据库和客户端来支持这些功能。要确定你的客户端能连接到正确的数据库,你要在数据库里配置一个支持故障转移的服务,并配置客户端的 TNS,让它知道如何在一个 Data Guard 集群里找到主库。
首先,创建一个支持故障转移的服务。我们要创建此服务,确定它在主库上启动,并确定它只在主库上启动。创建服务使用如下 SQL:
begin DBMS_SERVICE.CREATE_SERVICE ( service_name => 'JED_RW', network_name => 'JED_RW', aq_ha_notifications => TRUE, failover_method => 'BASIC', failover_type => 'SELECT', failover_retries => 30, failover_delay => 5); end; /此服务在数据库出现故障时会发送通知给客户端,允许查询语句在故障转移发生后继续运行。我使用命名 SID_RW 显示这时一个可读写的数据库(主库)。
下一步是确定新创建的服务永远只在主库运行。我们创建一个存储过程来实现此目的,如果当前数据库是主库它就启动此服务,如果是备库就停止。
create or replace procedure cmc_taf_service_proc is v_role VARCHAR(30); begin select DATABASE_ROLE into v_role from V$DATABASE; if v_role = 'PRIMARY' then DBMS_SERVICE.START_SERVICE('JED_RW'); else DBMS_SERVICE.STOP_SERVICE('JED_RW'); end if; end; /然后创建两个触发器,让数据库在启动和角色转换时运行此存储过程。我参考的文档,只提到建立一个触发器(角色转换时)。如果只创建一个,当你重启你的数据库时,它不会重启故障转移服务。所以我创建两个:
create or replace TRIGGER cmc_taf_service_trg_startup after startup on database begin cmc_taf_service_proc; end; / create or replace TRIGGER cmc_taf_manage_trg_rolechange after db_role_change on database begin cmc_taf_service_proc; end; /现在我们执行一次存储过程,确定服务正在运行,并归档当前日志,让以上更改同步到备库。
SQL> exec cmc_taf_service_proc; SQL> alter system archive log current;我们现在有了一个叫 JED_RW 的服务,可以让客户端连接。
SQL> show parameter service_names NAME TYPE VALUE ---------------- ----------- ------------ service_names string JED_RW有这个服务名存在还不够,你必须配置客户端的 TNS 名去连接它。客户端的 TNS 名应该类似如下:
JED_RW = (DESCRIPTION = (ADDRESS_LIST= (ADDRESS = (PROTOCOL = TCP)(HOST = dev-db1)(PORT = 1521)) (ADDRESS = (PROTOCOL = TCP)(HOST = dev-db2)(PORT = 1521)) ) (CONNECT_DATA = (SERVICE_NAME = JED_RW) (FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=30)(DELAY=5)) ) )这个 TNS 名里包含 Data Guard 配置里的两个主机,使用 JED_RW 服务名确定连接到主库。
如果你想连接特定的数据库,不管它是主是备,可以使用标准的 TNS 名,如下:
JED = (DESCRIPTION_LIST= (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = dev-db1)(PORT = 1521)) (CONNECT_DATA = (SERVICE_NAME = JED)) ) )当你的客户端使用新 TNS 名后,它们能在主备切换和故障转移操作后找到主库。如果客户端在运行一个查询,并且没有 DML 是在一个交易中,那在发生切换操作后,只要主备转换和故障转移在超过最大重试次数前完成,这个查询会继续工作,只是会有延迟。你应该多做几次切换实验,以确定 RETRIES 和 DELAY 参数如何设置合适。如果有一个正在进行中的交易,当客户端连接到新的主库后,查询将报错(`ORA-25403: transaction must roll back),并回滚。
进行主备切换(Switchover)现在你准备好做一次主备切换了,做之前先做些检查。首先在主库确认没有日志缺口:
SQL> select STATUS, GAP_STATUS from V$ARCHIVE_DEST_STATUS where DEST_ID = 2;应该返回 VALID 和 NO GAP。
查询v$tempfile视图确认备库的临时文件和主库一样。
删除 LOG_ARCHIVE_DEST_N 参数中的所有延迟应用重做日志设置,你要确认所有变化都在备库应用,才能确保无数据丢失。确认所有重做日志都已在备库应用,查询备库:
SQL> select NAME, VALUE, DATUM_TIME from V$DATAGUARD_STATS;不应该返回 transport lag 或 apply lag, finish time 应该为0.
检查完这些先决条件后,确认主库可以进行角色切换,查询主库:
SQL> select SWITCHOVER_STATUS from V$DATABASE;如果返回 TO STANDBY 或 SESSIONS ACTIVE,那么主库就可以进行切换。切换主库为备库命令为:
SQL> alter database commit to switchover to physical standby with session shutdown; SQL> shutdown immediate; SQL> startup mount;然后查询备库是否可以切换为主库,查询备库:
SQL> select SWITCHOVER_STATUS from V$DATABASE;如果返回 TO PRIMARY 或 SESSIONS ACTIVE,就可以切换。如果返回 SWITCHOVER LATENT 或 SWITCHOVER PENDING,就要去检查告警日志,看有什么问题,一般是需要应用一些日志。如果是需要应用日志的话,在备库执行如下命令:
SQL> recover standby database using backup controlfile;在应用日志前应该是 SWITCHOVER PENDING 状态,完成应用后,会变成 TO PRIMARY 或 SESSIONS ACTIVE状态。
现在可以切换备库为主库了:
SQL> alter database commit to switchover to primary with session shutdown; SQL> alter database open;完成主备切换后,在备库上启用日志应用:
SQL> alter database recover managed standby database using current logfiledisconnect from session;
进行故障转移(Failover)故障转移,一般用在主库发生故障后需要恢复服务的情况下。故障转移将备库转换为主库,但不把原主库(有故障,无法正常工作)切换为备库。当故障转移发生后,你必须重建主库,或者使用闪回数据库功能将主库回退到故障发生前,然后转换其为备库并启用日志应用。
我将故障转移分为三类:优雅、几乎优雅和标准。分类标准是主库故障的严重程度。故障转移不会是优雅的,但是你对故障的应对可以是优雅的。注意这些分类不是 Oracle 的官方分类,我个人创造这些分类用来代表故障转移的三个不同阶段。
优雅的故障转移如果当前备库是处于最大保护(maximum protection)模式,要进行故障转移,必须先修改为最大性能(maximum performance)模式。修改方法:
SQL> alter database set standby database to maximize performance;如果你还能将主库启动到挂载(mount)状态,你可以试着将刷新未传输的日志到备库。如果你能刷新,故障转移可能不会丢失任何数据。在本文中,我们上一节主备切换主库到了 JED2,我们现在故障转移回 JED:
SQL> startup mount SQL> alter system flush redo to 'JED';如果以上命令正常,日志已经传输到备库,我们需要在备库上应用它们。在下一节里,我们要确认所有重做日志是否都传输到了备库。
几乎优雅的故障转移为了尽可能少的丢失数据,你应该尝试将所有归档日志应用。你应该将主库上的所有归档日志复制到备库。可能有一些归档日志已经在备库存在,但这样你能有尽可能多的归档日志。然后你要解决备库中的任何日志缺口。
首先,复制所有主库的归档到备库,并在数据库中注册它们:
SQL> alter database register physical logfile '&logfile_path_name';检查是否有日志缺口:
SQL> select THREAD#, LOW_SEQUENCE#, HIGH_SEQUENCE# from V$ARCHIVE_GAP;如果有缺口存在,而主库上还有此日志文件,复制过来并注册。
标准故障转移在备库停止日志应用:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;结束应用任何日志:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE FINISH;如果以上命令有任何报错,检查相关告警日志和跟踪信息。一旦你执行了这个命令,备库就必须转换为主库,要不就得重建。
检查备库是否能转换为主库,执行:
SQL> select SWITCHOVER_STATUS from V$DATABASE;查询应该要返回 TO PRIMARY 或 SESSIONS ACTIVE,不然你可能还没有应用完所有日志。确认你执行了 RECOVER...FINISH命令。
转换备库为主库:
SQL> alter database commit to switchover to primary with session shutdown; SQL> alter database open;如果你有不止一个备库,你需要在其他备库上重启日志应用。下一步是重建原主库。如果配置了闪回数据库,重建会比较容易。
使用闪回数据库重建库现在你已经进行了故障转移,原主库需要重建为备库。使用闪回数据库重建原主库,首先需要获得原备库转换为主库时的 SCN。查询现主库:
SQL> SELECT to_char(STANDBY_BECAME_PRIMARY_SCN) from V$DATABASE;有了这个 SCN,你就可以使用闪回数据库功能将原主库回退到故障转移发生的时间点。在原主库上执行:
SQL> SHUTDOWN IMMEDIATE; SQL> STARTUP MOUNT; SQL> FLASHBACK DATABASE TO SCN &standby_became_primary_scn;如果没有开始闪回日志,最后一条命令会报错 ORA-38726: Flashback database logging is not on.,无法进行闪回。你就需要重新从新主库复制数据,重建原主库为备库。
如果命令成功执行,原主库就可以使用新主库的日志进行恢复。将原主库转换成物理备库,并启动日志应用进程:
SQL> ALTER DATABASE CONVERT TO PHYSICAL STANDBY; SQL> SHUTDOWN IMMEDIATE; SQL> STARTUP MOUNT; SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT FROM SESSION;然后就可以在新主库切换一次日志,查看新备库的日志应用是否正常,具体命令在本文第一部分。
客户端故障转移我很喜欢的一个功能是,当主备切换或故障转移发生后,客户端能够自动重连。在你的系统里,做下述实验,看结果如何。JED 是主库,JED2 是备库。客户端使用支持故障转移的 JED_RW 服务名。
首先,用 SYSTEM 用户和 JED_RW 服务名在 SQL*Plus 里登录主库:
SQL> connect system@jed_rw SQL> select db_unique_name from v$database;查询应该返回主库名 JED。然后做一次主备切换,在将备库转换为主库 alter database commit to switchover to primary with session shutdown; 这一步时,主备库均处于 MOUNT 状态。然后执行查询:
SQL> select db_unique_name from v$database;这时查询应该挂住,这是因为客户端正在尝试寻找主库,但当前又没有可用的主库。然后继续完成主备切换。
当主备切换完成后,客户端应该会重连并重新执行查询,查询完成后成功返回结果 JED2,因为现在主库已经切换为 JED2,不再是 JED。另一个很酷的测试方法是,执行一个执行时间非常长的查询,当查询结果返回,屏幕一直滚动时开始主备切换。你应该会看到屏幕暂停滚动一段时间,当切换完成后,又会继续滚动。
活动数据卫士(Active Data Guard)警告!活动数据卫士功能需要单独的授权。虽然打开此功能很容易,如果没有授权,你不应该使用它。
活动数据卫士是 11g 的新功能,它允许你的物理备库在应用日志时处于只读打开状态。这明显是一个很有用的功能。能够允许主库有一个物理备库作为备份,并能在保持备库数据更新的同时读取备库,这是一个很好的功能。Oracle 也知道,所以这个功能需要单独买授权。
开启活动数据卫士功能十分容易。你只需要打开在你的数据库后再启动日志应用:
SQL> STARTUP MOUNT SQL> ALTER DATABASE OPEN; SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE DISCONNECT;之后你就可以登录备库,并执行查询。你可以执行如下查询确认:
SQL> SELECT name status, database_role, open_mode logins, log_mode FROM v$instance, v$database;在开启活动数据卫士功能后,查询应该返回 PHYSICAL STANDBY,READ ONLY WITH APPLY 和 ARCHIVELOG。
当你开启活动数据卫士功能后,你需要允许用户根据需要连接到正确的数据库。我创建第二个服务叫 SID_RO,并让它只在备库启动。这个名字显示你连接的是一个只读(Read Only)数据库,而不是读写数据库。这个服务名的创建跟 SID_RW 类似:
begin DBMS_SERVICE.CREATE_SERVICE ( service_name => 'JED_RO', network_name => 'JED_RO', aq_ha_notifications => TRUE, failover_method => 'BASIC', failover_type => 'SELECT', failover_retries => 30, failover_delay => 5); end; /修改原启动服务的存储过程:
create or replace procedure cmc_taf_service_proc is v_role VARCHAR(30); begin select DATABASE_ROLE into v_role from V$DATABASE; if v_role = 'PRIMARY' then begin DBMS_SERVICE.STOP_SERVICE('JED_RO'); exception when others then null; end; DBMS_SERVICE.START_SERVICE('JED_RW'); else begin DBMS_SERVICE.STOP_SERVICE('JED_RW'); exception when others then null; end; DBMS_SERVICE.START_SERVICE('JED_RO'); end if; end; /现在你有了一个活动数据卫士的配置,你的客户端能连接到合适的数据库实例,并可以在出现主备切换和故障转移时自动重连。
备份最后,如果不讨论下备份,那对 Data Guard 的介绍还不算完整。Data Guard 实质上就是也是备份,但这不意味着你就不需要 RMAN 备份了。你已经花时间去启用了强制记录日志,那你也应该做点备份。
有了 Data Guard,你的 RMAN 备份在主库或者备库都可以执行。但既然你已经配置了物理备库,你应该减轻点主库的负载。基本上,能在主库执行的标准的备份命令或脚本,也能在备库执行,但也有几个值得注意地方。这些 Oracle 官方文档都有,我只提几个关键的事情:
你应该使用恢复目录(Recovery Catalog)。这是因为主库需要知道备库已经存在了哪些备份文件。你不需要在恢复目录中注册备库,恢复目录能认出它是备库。
你不能备份备库的控制文件,所以不要在主库关掉所有的备份,至少需要在主库备份控制文件和参数文件。
备份和恢复可以写一整篇文章,我只是讲下我是如何配置备份的,让你能从这里开始,修改并形成自己的策略。测试下,确认你能从你当前实现的备份设置中恢复。在运行备份前,你需要配置一些基本的东西。
确认开启控制文件和 spfile 自动备份:
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;根据你的需要设置备份文件保留策略:
RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 3 DAYS;如果一个文件已经有备份,并且检查点 SCN 相同,就不备份:
RMAN> CONFIGURE BACKUP OPTIMIZATION ON;只在主库的归档日志已经在备库应用(或者配置为已经传输到备份)后才删除:
RMAN> CONFIGURE ARCHIVELOG DELETION POLICY TO APPLIED ON ALL STANDBY;允许 RMAN 在主备间重新同步:
RMAN> CONFIGURE DB_UNIQUE_NAME P10AC CONNECT IDENTIFIER ‘JED’; RMAN> CONFIGURE DB_UNIQUE_NAME P11AC CONNECT IDENTIFIER 'JED2';在主库我仍然备份归档日志。首先,在主备库都备份归档提供了冗余。其次,当发生需要恢复的事件(比如数据文件下线等)后,我在主库已经有归档了。我需要删除过期的归档,以清理磁盘空间。在Data Guard 环境下,不能使用标准的在单机删除归档的命令,两者有一点小区别。因为我们必须使用恢复目录,我创建了一个全局脚本(global script):
create global script dg_primary_arch { backup archivelog all; delete noprompt archivelog all completed before 'sysdate-.5'; delete noprompt backup of archivelog all completed before 'sysdate-2'; }在备库我运行标准的全库和归档备份,并删除过期的备份集。在 Data Guard 环境下,将备份归档包含在备份全库的命令里,会经常导致报错 RMAN-08137: WARNING: archived log not deleted, needed for standby or upstream capture process。为避免此报错,你应该将备份归档放在单独的命令里。我还是创建一个全局脚本:
create global script dg_standby_full { backup database plus archivelog; delete noprompt archivelog all completed before 'sysdate-1'; delete noprompt obsolete; }另外一个有用的技巧是,如果可能,使用共享文件系统进行备份。这样你在两台服务器上都可以访问备份文件。这样,当你需要恢复时,你不需要从另一台服务器上复制文件了。但如果使用共享文件系统的话,你的归档备份虽然有两份,却都放在一个文件系统里,如果硬盘出现故障,两份备份都会丢失。
总结Oracle 11g 的 Data Guard 是一个很好的功能,配置起来相对容易,提供了在主库异常时故障转移的功能。它也能将主备的备份操作转移到备库执行,减轻主备负载。另外,Data Guard Broker 是一个宣称能简化管理的工具,但介绍这个工具就得需要另外一篇文章了。