Decode360's Blog

业精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

  BlogJava :: 首页 :: 新随笔 :: 联系 ::  :: 管理 ::
  302 随笔 :: 26 文章 :: 82 评论 :: 0 Trackbacks
本文作者: junsansi     转载网址: http://www.5ienet.com/index.shtml
 
 
第三部分逻辑standby(3)角色转换  2008.02.22
 
    关于角色转换的一些概念在物理standby 章节的时候已经讲了很多,在概念和操作方式上二者基本一致,不过如果你真正深刻理解了物理standby 和逻辑standby,你会意识到,对于逻辑standby 而言,不管是switchover还是failover,怎么操作起来,都这么怪怪的呢~~~
 
逻辑standby之switchover
 
    要在primary 和逻辑standby 之间切换角色,一般是从操作primary 开始。

    提示:
    如果primary 或逻辑standby 是rac 结构,切记只保留一个实例启动,其它实例全部shutdown。等角色转换操作完成之后再启动其它实例,角色转换的操作会自动传播到这些实例上,并不需要你再对这些实例单独做处理。

 
一、准备工作

1、检查primary 和逻辑standby 的初始化参数设置,常规的检查包括:

    确保fal_server,fal_client 值设置正确
    确保log_archive_dest_n 参数设置正确
    更多可能涉及的初始化参数可以参考2.1 中的第4 小章
 
    首先来看当前的primary数据库:

    JSSWEB> show parameter fal
    NAME                       TYPE        VALUE
    -------------------------- ----------- -------------------------------
    fal_client                 string      jssweb
    fal_server                 string      jsspdg

 

    JSSWEB> show parameter name_convert
    NAME                       TYPE        VALUE
    -------------------------- ----------- -------------------------------
    db_file_name_convert       string      oradata\jsspdg, oradata\jssweb
    log_file_name_convert      string      oradata\jsspdg, oradata\jssweb

 

    JSSWEB> show parameter log_archive_dest
    NAME                       TYPE        VALUE
    -------------------------- ----------- -------------------------------
    log_archive_dest           string
    log_archive_dest_1         string      LOCATION=E:\ora10g\oradata\jssweb\arc
                                           VALID_FOR=(ALL_LOGFILES,ALL_ROLES)
                                           DB_UNIQUE_NAME=jssweb
    log_archive_dest_2         string      service=jsspdg OPTIONAL LGWR SYNC AFFIRM
                                           VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)
                                           DB_UNIQUE_NAME=jsspdg
    ................
    ................
    ................
    log_archive_dest_state_1   string      ENABLE
    log_archive_dest_state_2   string      defer

    由于此处primary 的初始化参数并不合适,为了避免其转换之后发生错误,我们需要提前做些修改:

    JSSWEB> alter system set log_archive_dest_2='location=e:\ora10g\oradata\jssweb\std\valid_for=(standby_logfiles,standby_role) db_unique_name=jssweb';
   
系统已更改。

 

    JSSWEB> alter system set log_archive_dest_1='location=e:\ora10g\oradata\jssweb\arc\valid_for=(online_logfiles,all_roles) db_unique_name=jssweb';
   
系统已更改。

 

    JSSWEB> alter system set log_archive_dest_state_2='enable';
   
系统已更改。

 

    JSSWEB> alter system set fal_server='jssldg';
   
系统已更改。

 

    --xx_file_name_convert 这两个参数无法动态修改,因此我们首先修改 spfile ,然后再重启一下数据库
    JSSWEB> alter system set db_file_name_convert='oradata\jssldg','oradata\jssweb' scope=spfile;
   
系统已更改。

    JSSWEB> alter system set log_file_name_convert='oradata\jssldg','oradata\jssweb' scope=spfile;
   
系统已更改。

 

    JSSWEB> startup force

 
    然后再看看待转换的逻辑standbstandby

    JSSLDG> show parameter fal
    NAME                   TYPE        VALUE
    ---------------------- ----------- --------------------
    fal_client           string
    fal_server           string

 

    JSSLDG> show parameter file_name
    NAME                   TYPE        VALUE
    ---------------------- ----------- --------------------
    db_file_name_convert   string      oradata\jssweb, oradata\jssldg
    log_file_name_convert  string      oradata\jssweb, oradata\jssldg

 

    JSSLDG> show parameter log_archive
    NAME                   TYPE        VALUE
    ---------------------- ----------- --------------------
    log_archive_config     string      DG_CONFIG=(jssweb,jsspdg,jssldg)
    log_archive_dest       string
    log_archive_dest_1     string      location=E:\ora10g\oradata\jssldg\arc\
                                       valid_for=(online_logfiles,all_roles)
                                       db_unique_name=jssldg
    log_archive_dest_10    string
    log_archive_dest_2     string      location=E:\ora10g\oradata\JSSLDG\std\
                                       valid_for=(standby_logfiles,standby_role)
                                       db_unique_name=JSSLDG
    .......................
    .......................

 
 
    对于待转换的逻辑standby 中,某些初始化参数也可以不设置,不过走到这一步了,顺手全设置一遍。

    JSSLDG> alter system set fal_server='jssweb';
    系统已更改。


    JSSLDG> alter system set fal_client='jssldg';
    系统已更改。


    JSSLDG> alter system set log_archive_dest_3='service=jssweb lgwr async valid_for=(online_logfiles,primary_role) db_unique_name=jssweb';
    系统已更改。

 
2、检查primary 数据库是否配置了standby redologs

    JSSWEB> select * from v$standby_log;
    未选定行

 
    对于逻辑standby 数据库,standby redologs 是必须的,因此我们需要为当前的primary 创建几个standbyredologs。

    JSSWEB> alter database add standby logfile group 4 ('e:\ora10g\oradata\jssweb\standbyrd01.log') size 20m;
    数据库已更改。
    .....................
    .......................
    .........................
    JSSWEB> alter database add standby logfile group 8 ('e:\ora10g\oradata\jssweb\standbyrd05.log') size 20m;
    数据库已更改。

 
 
二、检查primary数据库状态
 
    在当前的primary 数据库查询v$database 视图中的switchover_status 列,查看当前primary 数据库状态。

    JSSWEB> select switchover_status from v$database;
    SWITCHOVER_STATUS
    --------------------
    TO STANDBY

 
    如果该查询返回TO STANDBY 或SESSIONS ACTIVE 则表示状态正常,可以执行转换操作,如果否的话,就需要你先检查一下当前的dataguard 配置,看看是否
 
 
三、准备转换primary为逻辑standby
 
    执行下列语句,将primary 置为准备转换的状态:

    JSSWEB> alterdatabasepreparetoswitchovertologicalstandby;
    数据库已更改。

 
    查看一下switchover_status 的状态,哟,果然变成准备ing 啦~~

    JSSWEB> select switchover_status from v$database;
    SWITCHOVER_STATUS
    --------------------
    PREPARING SWITCHOVER

 
 
四、准备转换逻辑standby为primary
 
    我们一定要学习oracle 这种逻辑,甭管想做什么,都得先有个准备的过程~

    JSSLDG> alterdatabasepreparetoswitchovertoprimary;
    数据库已更改。

    JSSLDG> select switchover_status from v$database;
    SWITCHOVER_STATUS
    --------------------
    PREPARING SWITCHOVER

 
 
五、再次检查primary数据库状态

 

    JSSWEB> select switchover_status from v$database;
    SWITCHOVER_STATUS
    --------------------
    TO LOGICAL STANDBY

 
    注意:这步虽然不做什么操作,但检查结果却非常重要,它直接关系到switchover 转换是否能够成功。逻辑standby 执行完prepare 命令之后,就会生成相应的LogMiner 字典数据(就像我们前面创建逻辑standby 时,primary 会生成LogMiner 字典数据一样),只有它正常生成并发送至当前的primary,转换操作才能够继续下去。不然当前的primary 数据库在转换完之后,可能就失去了从新的primary 接收redo 数据的能力了。
 
    因此,如果上述查询的返回结果不是:TO LOGICAL STANDBY 的话,你可能就需要取消此次转换,检查原因,然后再重新操作了。

    提示:
    取消转换可以通过下列语句:
    ALTER DATABASE PREPARE TO SWITCHOVER CANCEL;
    需要分别在primary 和逻辑standby 执行。

 

 

六、转换primary为逻辑standby
 
    执行下列语句:

    JSSWEB> alterdatabasecommittoswitchovertologicalstandby;
    数据库已更改。

 
    该语句需要等待当前primary 所有事务全部结束。同时该语句也会自动拒绝用户发布的新事务或修改需求。为确保该操作尽可能快的执行,最好自开始切换操作起就禁止所有用户的操作。
    该命令执行完之后,这个primary 就已经成为新的逻辑standby 了。不过在新primary 执行完转换之前,不要关闭当前这个数据库。
 
 
七、再次检查逻辑standby状态
 
    逻辑standby 在接收到前primary 的转换消息,并应用完相关的redo 数据之后,会自动暂停sql 应用,然后查询switchover_status 的状态,应该为:TO PRIMARY

    JSSLDG> select switchover_status from v$database;
    SWITCHOVER_STATUS
    --------------------
    TO PRIMARY

 
 
八、转换逻辑standby为primary
 
    最后的工作总会在逻辑standby 上操作,通过上列语句,将该逻辑standby 转换为新的primary。

    JSSLDG> alterdatabasecommittoswitchovertoprimary;
    数据库已更改。

 
    转换完成
 
 
九、启动新逻辑standby的sql应用

    最后启动新逻辑standby 的sql 应用。

    JSSWEB> alter database start logical standby apply;
    数据库已更改。

 
    提示:还记的我们的jsspdg 吗,虽然它也是standby(物理),不过它现在也并非这个dataguard 配置中的一员了,这也是由于逻辑standby 自身特性决定的,每一个逻辑standby 都相当于是一个不同于primary 的数据库(DBID都不同),因此在逻辑standby 完成了转换之后,相当于原primary 已经消失,因此原primary 配置的物理standby也失去了主从参照,不过原primary 配置的逻辑standby 不会有影响。
 
 
逻辑standby之failover

    前面学习物理standby 的failover 时我们提到过,failover 有可能会丢失数据(视当前的数据库保护模式而定),对于逻辑standby 也一样;物理standby 在做failover 演示时还提到过,所有的操作都会在standby 端执行,对于逻辑standby 这也一样,甚至对于明确提及在前primary 执行的,你不执行,也没关系,毕竟对于failover,我们假设的就是,primary 已经over 了:)
 
 
一、准备工作要充分
 
    准备工作可以从以下几个方面着手:
 
1、检查及处理丢失的归档
 
    虽然本步不是必须的,但如果希望尽可能少丢失数据,除了数据保护模式之外,本步操作也非常重要。如果此时primary 仍可被访问,首先检查当前的归档日志序号与逻辑standby 是否相同:

    JSSLDG> select max(sequence#) from v$archived_log;
    MAX(SEQUENCE#)
    --------------
    24

 

    JSSWEB> select sequence#,applied from dba_logstdby_log;
    SEQUENCE#  APPLIED
    ---------- --------
    23         YES
    24         YES
   
已选择2 行。

 
    提示:如果primary 的数据库已经无法打开,您就只好直接到磁盘上查看归档目录中的序号来与standby端做比较了。
 
    如果不同序号,则将primary 尚未发送至standby 的归档文件手工复制到待转换的逻辑standby 服务器,然后在standby 端通过ALTER DATABASE REGISTER LOGICAL LOGFILE ''; 命令将文件手工注册
    如果standby 与primary 的归档序号相同,但某些序号的applied 状态为no,建议你检查一下当前standby是否启动了SQL 应用:)。
 
2、检查待转换逻辑standby 的日志应用情况

    可以通过查询v$logstdby_progress 视图:

    JSSWEB> select applied_scn,latest_scn from v$logstdby_progress;
    APPLIED_SCN LATEST_SCN
    ----------- ----------
    1259449     1259453

 
    如果两值一致,表示所有接收到的归档都已经应用了。
 
3、检查及修正待转换逻辑standby 的初始化参数配置

    确认待转换的逻辑standby 配置了正确的归档路径,不仅是写本地的归档,还要有写远程的归档,不然转换完之后,这台新的primary 就成了光杆司令了。

    JSSWEB> show parameter log_archive_dest
    .......................

 
    当然一般来说,我们都是推荐在创建standby 的同时将一些用于角色切换的初始化参数也配置好(primary 和standby 端都应如此),以减小切换时操作的时间,提高切换效率。
 

二、激活新的primary数据库
 
    首先查看当前操作的角色

    JSSWEB> select database_role,force_logging from v$database;
    DATABASE_ROLE    FOR
    ---------------- ---
    LOGICAL STANDBY YES

    注意,如果当前force_logging 为no,务必执行:Alter database force logging;

    转换standby 角色为primary

    JSSWEB> altealterdatabaseactivatelogicalstandbydatabasefinishapply;
    数据库已更改。

 
    该语句主要是停止待转换的逻辑standby 中RFS 进程,并应用完当前所有已接收但并未应用的redo 数据,然后停止sql 应用,将数据库转换成primary 角色。

    JSSWEB> select database_role,force_logging from v$database;
    DATABASE_ROLE    FOR
    ---------------- ---
    PRIMARY          YES

 
    基本上到这一步,我们可以说角色转换的工作已经完成了,但是注意,活还没有干完!
 
    此处与逻辑standby 的switchover 同理,切换完之后,原dg 配置就失效了(不仅原物理standby 没了,原逻辑standby 也失去了参照,看看,逻辑standby 的failover 确实威力巨大呀,怪不得逻辑standby 用的人这么人呢,环境脆弱肯定是原因之一啊),因此我们需要做些设置,重新将原来的standby 再加入到新的dg 配置环境中。
 
 
三、修复其它standby
 
    注意哟,逻辑standby 的修复可并不像物理standby 那样简单,每个逻辑standby 都相当于是独立的数据库,如果你不希望重建逻辑standby 的话呢,oracle 倒是也提供了其它解决方案(虽然不一定好使):
 
1、在各个原逻辑standby 中创建数据库链,连接到新的primary
 
    注意,数据库链中用于连接新primary 的用户必须拥有SELECT_CATALOG_ROLE 角色。

    JSSLDG2> alter session disable guard;
    会话已更改。
    JSSLDG2> create database link getjssweb connect to jss identified by jss using 'jssweb';
    数据库链接已创建。
    JSSLDG2> alter session enable guard;
    会话已更改。

 
    验证一下数据链是否能够正常访问:

    JSSLDG2> select sysdate from dual@getjssweb;
    SYSDATE
    --------------
    23-2 月-08


    提示:关于alter session enable|disable guard 语句,用于允许或禁止用户修改逻辑standby 中的结构。例如:

    JSSLDG2> conn jss/jss
   
已连接。

 

    JSSLDG2> select * from b;
    ID
    ----------
    1
    2
    3
    4
    5
    6
    7
    8
   
已选择8 行。

 

    JSSLDG2> alter table b rename to a;
    alter table b rename to a
    *
   
1 行出现错误:
    ORA-16224: Database Guard
已启用

 

    JSSLDG2> alter session disable guard;
   
会话已更改。

 

    JSSLDG2> alter table b rename to a;
   
表已更改。

 
2、重新启动SQL 应用

    在各个逻辑standby 执行下列语句启动sql 应用(注意更新dblinkName):

    JSSLDG2> alter database start logical standby apply new primary getjssweb;
    数据库已更改。

 
    如果你运气好,等语句执行完之后,恢复过程就完成了。如果你非常不幸的碰到了ORA-16109 错误,那么我不得不告诉你,恐怕你得重建逻辑standby 了。所以,祝你好运吧:)

    语句顺利执行完之后,我们来验证一下:

    JSSWEB> alter system switch logfile;
   
系统已更改。

 

    JSSWEB> select max(sequence#) from v$archived_log;
    MAX(SEQUENCE#)
    --------------
    862

 

    JSSLDG2> select sequence#,applied from dba_logstdby_log;
    SEQUENCE#  APPLIED
    ---------- --------
    862        NO


 
    注意:出现问题了!!
 
    日志是传输过去了,但是逻辑standby 并没有开始应用,怎么回事?
 
    我们先来确认一下standby 的各进程状态:

    JSSLDG2> select process,status,group#,thread#,sequence#,block#,blocks from v$managed_standby;
    PROCESS   STATUS       GROUP#    THREAD#    SEQUENCE# BLOCK#     BLOCKS
    --------- ------------ --------- ---------- ---------- ---------- ----------
    ARCH      CLOSING                       4          16385      1836
    ARCH      CLOSING                       862                 18
    RFS       IDLE         N/A                0                   0
    RFS       IDLE                          863                 1


    看起来也是正常的,接收完了862,正在等待863,但是,为什么不应用呢。
 
    手工查询一下新primary 生成的归档日志情况:

    JSSWEB> select sequence#,name,COMPLETION_TIME from v$archived_log where sequence#>855;
    SEQUENCE# NAME                                                     COMPLETION_TIME
    ---------- -------------------------------------------------------- -------------------
    856        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_856_641301252.ARC      2008-02-21 10:15:42
    857        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_857_641301252.ARC      2008-02-21 10:16:46
    858        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_858_641301252.ARC      2008-02-23 14:15:18
    859        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_859_641301252.ARC      2008-02-23 14:56:55
    860        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_860_641301252.ARC      2008-02-23 14:57:03
    861        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_861_641301252.ARC      2008-02-23 16:58:14
    861        jssldg2                                                  2008-02-23 16:58:16
    862        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_862_641301252.ARC      2008-02-23 17:08:57
    862        jssldg2                                                  2008-02-23 17:08:57
    863        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_863_641301252.ARC      2008-02-23 17:19:48
    863        jssldg2                                                  2008-02-23 17:20:59
    864        E:\ORA10G\ORADATA\JSSWEB\ARC\LOG1_864_641301252.ARC      2008-02-23 17:21:11
    864        jssldg2                                                  2008-02-23 17:21:13
    已选择13 行。


    发现了一点点痕迹,我们的切换操作是下午3 点左右进行的,期间还产生了序列号为860,861 之类的归档文件,但并未传输至standby,是不是因为这些文件中包含了一部分应被应用的数据,因此造成standby
接收到的新primary 传输过来的归档scn 与最后应用的scn 不连续,所以无法应用?再来验证一下:

    JSSLDG2> select applied_scn,latest_scn from v$logstdby_progress;
    APPLIED_SCN LATEST_SCN
    ----------- ----------
    1259449     1284126


    果然如此,应用的scn 与最后的scn 确实不匹配,剩下的就好解决了,把所有可疑的应传输到standby的归档文件手工复制到standby,然后通过alter 命令注册一下:

    JSSLDG2> alter database register logical logfile 'E:\ora10g\oradata\jssldg2\std\LOG1_859_641301252.ARC';
    数据库已更改。
    JSSLDG2> alter database register logical logfile 'E:\ora10g\oradata\jssldg2\std\LOG1_860_641301252.ARC';
    数据库已更改。
    JSSLDG2> alter database register logical logfile 'E:\ora10g\oradata\jssldg2\std\LOG1_861_641301252.ARC';
    数据库已更改。

 
    提示:复制文件的时候尽可能把相近时间段的归档文件都拷过来,不用担心无用归档会不会影响到应用,oracle 会自动判断归档中的scn,对于已经应用过的正常情况下是不会重复应用的,因此我们把
859,860,861 全部复制过来。
    再查看一下应用状态:

    JSSLDG2> select sequence#,applied from dba_logstdby_log;
    SEQUENCE# APPLIED
    ---------- --------
    862        CURRENT
    863        CURRENT

 
    哈哈,已经开始应用了。逻辑standby 恢复成功!想起官方文档中有一句提示,说的是在打开新的primary数据库,生成数据字典之前,不要执行任何DDL,不然就只能重建逻辑standby 了,估计就是担心执行ddl后不幸触发日志切换,造成逻辑standby 接收新primary 传来的归档文件不连续,无法顺利应用。
 
    切换完成之后,在修复逻辑standby 的同时,顺手打扫一下战场,比如设置新primary 数据库的备份策略,以及考虑如何修复前故障的primary 等等,dba 这份工作,人前看起来光鲜,如果你已经下定决心要从事这行,那对于人后的辛苦一定要有深刻心理准备哟,你看看像上面这种情况,primary 只要随随便便宕个机,引之而来的工作量就够我们忙活的。
 
 
    也许这个时候dba 需要的不仅是保持清晰的大脑,还要能打开思路,此时我们更不妨考虑在做角色切换和修复损坏的primary 之间做个选择,究竟哪个更快,哪个更简便一些呢,你看,干dba 这行,不仅压力大,不仅要本领过硬,不仅要耐心细致,关键时刻还要保持清醒的头脑,额地神耶,太刺激啦,太有挑战啦~~~~~~




-The End-

posted on 2009-02-25 21:46 decode360-3 阅读(697) 评论(0)  编辑  收藏 所属分类: DBA

只有注册用户登录后才能发表评论。


网站导航: