?
?
第三部分邏輯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????? 2???????? 1????????? 4????????? 16385????? 1836
??? ARCH????? CLOSING????? 6???????? 1????????? 862??????? 1????????? 18
??? RFS?????? IDLE???????? N/A?????? 0??????????0??????????0????????? 0
??? RFS?????? IDLE???????? 3?????????1????????? 863??????? 2????????? 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-