1. 程式人生 > >Oracle - 通過dg,完成單例項到rac的遷移

Oracle - 通過dg,完成單例項到rac的遷移

一、概述

本文將介紹如何給單例項搭建一個rac dg,以及如何對其進行角色轉換,完成從單例項到rac的遷移。預先具備的知識(rac搭建,單例項-單例項dg搭建)

 

二、實驗環境介紹

主庫(已有資料庫例項prod)
prod:192.168.56.102,sid:prod,version:11.2.0.4

從庫rac(已安裝rac軟體,無資料庫例項)
rac1:192.168.56.11,version:11.2.0.4
rac2:192.168.56.12,version:11.2.0.4

 

三、搭建dg

1. 主庫開啟歸檔模式,並強制寫日誌

先檢視資料庫的歸檔狀態以及是否開啟強制寫日誌,從下圖可以看到目前資料庫並沒有開啟歸檔,也沒有開啟強制寫日誌
SQL> select log_mode, force_logging from v$database;

資料庫在mount狀態下開啟歸檔
[oracle@prod ~]$ mkdir -p /u01/app/oracle/oradata/prod/archivelog
SQL> alter system set log_archive_dest_1='location=/u01/app/oracle/oradata/prod/archivelog/' scope=spfile;
SQL> shutdown immediate;
SQL> startup mount; 
SQL> alter database archivelog;
SQL> alter database open;

強制日誌寫,資料庫在open狀態就能修改
SQL> alter database force logging;

再來檢視資料庫的歸檔狀態以及是否開啟強制寫日誌
SQL> select log_mode, force_logging from v$database;

 

2. 主庫開啟dataguard開關

SQL> alter system set log_archive_config='dg_config=(prod,proddg)';  # prod是主庫的db_unique_name,proddg是從庫的db_unique_name,這裡只需要把主從環境中所有db_unique_name列出來就行,誰先誰後並不影響。

 

3. 主庫設定遠端歸檔

SQL> alter system set log_archive_dest_3='service=proddg valid_for=(online_logfiles,primary_role) db_unique_name=proddg';

 

4. 將主庫的口令檔案傳送給從庫

[oracle@prod ~]$ scp $ORACLE_HOME/dbs/orapw$ORACLE_SID 192.168.56.11:$ORACLE_HOME/dbs/orapwproddg1
[oracle@prod ~]$ scp $ORACLE_HOME/dbs/orapw$ORACLE_SID 192.168.56.12:$ORACLE_HOME/dbs/orapwproddg2
 

5. 從庫準備引數檔案

[oracle@rac1 ~]$ vi /home/oracle/pfile_initproddg1.ora  # 只在從庫節點1上建立

*.audit_file_dest='/u01/app/oracle/admin/proddg/adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='+DATA/PRODDG/CONTROLFILE/control01.ctl'
*.db_block_size=8192
*.db_domain=''
*.db_name='prod'
*.diagnostic_dest='/u01/app/oracle'
*.log_archive_config='dg_config=(prod,proddg)'
*.log_archive_dest_2='location=+DATA/PRODDG/ARCHSTDLOG/ valid_for=(standby_logfiles,standby_role) db_unique_name=proddg'
*.memory_target=838860800
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='exclusive'
*.standby_file_management=auto
*.db_unique_name='proddg'
*.db_file_name_convert='/u01/app/oracle/oradata/prod/','+DATA/proddg/datafile/','/u01/app/oracle/oradata/prod/','+DATA/proddg/tempfile/'
*.log_file_name_convert='/u01/app/oracle/oradata/prod/','+DATA/proddg/onlinelog/'
*.cluster_database=false
proddg1.undo_tablespace='UNDOTBS1'
proddg2.undo_tablespace='UNDOTBS2'
proddg1.instance_number=1
proddg2.instance_number=2
proddg1.thread=1
proddg2.thread=2


6. 從庫中準備相關目錄

[oracle@oradg ~]$ mkdir -p /u01/app/oracle/admin/proddg/adump  # 從庫兩節點都建立

[grid@rac1 ~]$ asmcmd  # 只在從庫節點1上建立
ASMCMD> lsdg
ASMCMD> cd data
ASMCMD> mkdir PRODDG
ASMCMD> cd PRODDG
ASMCMD> mkdir ARCHIVELOG
ASMCMD> mkdir ARCHSTDLOG
ASMCMD> mkdir CONTROLFILE
ASMCMD> mkdir DATAFILE
ASMCMD> mkdir ONLINELOG
ASMCMD> mkdir TEMPFILE

 

7. 從庫生成spfile檔案

[oracle@oradg ~]$ export ORACLE_SID=proddg1  # 只在從庫節點1上做
[oracle@oradg ~]$ sqlplus / as sysdba
SQL> startup nomount pfile='/home/oracle/pfile_initproddg1.ora';
SQL> create spfile='+DATA/PRODDG/spfileproddg.ora' from pfile='/home/oracle/pfile_initproddg1.ora';
SQL> shutdown abort
SQL> exit

 

8. 從庫生成pfile檔案

[oracle@rac1 ~]$ echo "SPFILE='+DATA/PRODDG/spfileproddg.ora'" > $ORACLE_HOME/dbs/initproddg1.ora  # 節點1生成
[oracle@rac2 ~]$ echo "SPFILE='+DATA/PRODDG/spfileproddg.ora'" > $ORACLE_HOME/dbs/initproddg2.ora  # 節點2生成
 

9. 主庫生成全庫備份和standby controlfile並拷貝至從庫節點1

[oracle@prod ~]$ export ORACLE_SID=prod
[oracle@prod ~]$ rman target /
RMAN> backup database format '/home/oracle/prod_%t_%s';
RMAN> backup current controlfile for standby format '/home/oracle/prod_control01.ctl';

[oracle@prod ~]$ scp /home/oracle/prod* 192.168.56.11:/home/oracle/backup
 

10. 在從庫節點1啟動例項,並恢復控制檔案

[oracle@oradg ~]$ export ORACLE_SID=proddg1  # 只在從庫節點1上做
[oracle@oradg ~]$ sqlplus / as sysdba
SQL> startup nomount

再開啟一個視窗
[oracle@oradg ~]$ export ORACLE_SID=proddg1  # 只在從庫節點1上做
[oracle@oradg ~]$ rman target /
RMAN> restore controlfile from '/home/oracle/backup/prod_control01.ctl';
RMAN> alter database mount;
RMAN> catalog start with '/home/oracle/backup';  # 將備份片的資訊重新註冊到控制檔案中

 

11. 在從庫節點1還原和恢復資料庫備份

# 具體的資料檔案和臨時檔案編號可以在主庫通過dba_data_files,dba_temp_files查到
# 偶然通過實驗發現一個比較神奇的現象,因為我前面在引數檔案中定義了db_file_name_convert和log_file_name_convert,所以控制檔案中的logfile和datafile的路徑已經被轉換好了,下面run中set newname for xxx其實是沒必要的。
RMAN> run {
set newname for datafile 1 to '+DATA';
set newname for datafile 2 to '+DATA';
set newname for datafile 3 to '+DATA';
set newname for datafile 4 to '+DATA';
set newname for datafile 5 to '+DATA';
set newname for tempfile 1 to '+DATA';
restore database;
switch datafile all;
switch tempfile all;
}

RMAN> recover database;
以下錯誤可以暫時忽略,因為開啟同步後,dg會自動同步歸檔日誌

unable to find archived log
archived log thread=1 sequence=8
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of recover command at 12/16/2019 15:09:48
RMAN-06054: media recovery requesting unknown archived log for thread 1 with sequence 8 and starting SCN of 1019774


12. 在從庫節點1建立standby log

# 新增的日誌的大小跟主庫的onlinelog保持一致,數量多兩組(主庫的onlinelog資訊檢視v$log)
SQL> alter database add standby logfile thread 1 group 21 ('+data') size 50M;
SQL> alter database add standby logfile thread 1 group 22 ('+data') size 50M;
SQL> alter database add standby logfile thread 1 group 23 ('+data') size 50M;
SQL> alter database add standby logfile thread 1 group 24 ('+data') size 50M;
SQL> alter database add standby logfile thread 2 group 25 ('+data') size 50M;
SQL> alter database add standby logfile thread 2 group 26 ('+data') size 50M;
SQL> alter database add standby logfile thread 2 group 27 ('+data') size 50M;
SQL> alter database add standby logfile thread 2 group 28 ('+data') size 50M;

 

13. 主庫配置服務命名

[oracle@prod ~]$ vi $ORACLE_HOME/network/admin/tnsnames.ora

# 這裡只需要指向節點1就行了

proddg =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.56.11)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = proddg)
    )
  )

 

14. 從庫開啟應用日誌

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

 

15. 主庫切換歸檔

SQL> alter system switch logfile;

 

16. 開啟從庫

當從庫應用歸檔一段時間後,就關閉應用歸檔日誌,開啟從庫。
SQL> alter database recover managed standby database cancel;
SQL> alter database open;
SQL> alter database recover managed standby database using current logfile disconnect from session;

 

17. 驗證同步

主庫做修改
SQL> update scott.emp set sal=30;
SQL> commit;

從庫查詢
SQL> select * from scott.emp;

至此,從庫rac1已經搭建完成,接下來將rac2加入進來

 

四、把從庫節點2加入到叢集中

18. 主庫再新增一個undo tablespace

# 因為從庫是2節點的rac,每個rac節點都需要使用自己的undo tablespace,所以主庫新增的undotbs2同步到同庫中,給從庫節點2使用
SQL> create undo tablespace undotbs2 datafile '/u01/app/oracle/oradata/prod/undotbs02.dbf' size 1G autoextend on maxsize unlimited;

 

19. 在從庫節點1修改資料庫為rac模式

SQL> alter system set cluster_database=true scope=spfile;
SQL> alter system set cluster_database_instances=2 scope=spfile;
SQL> shutdown immediate 
SQL> startup
SQL> alter database recover managed standby database using current logfile disconnect from session;
 

20. 啟動從庫節點2

[oracle@rac2 ~]$ export ORACLE_SID=proddg2 
[oracle@rac2 ~]$ sqlplus / as sysdba
SQL> startup
 

21. 驗證修改

主庫做修改
SQL> update scott.emp set sal=40;
SQL> commit;
SQL> alter system switch logfile;

從庫查詢
SQL> select * from scott.emp;
 

22. 在從庫節點1註冊資料庫到叢集中

註冊資料庫
[oracle@rac1 ~]$ srvctl add database -d proddg -n prod -o /u01/app/oracle/product/11.2.0/db_1 -p +DATA/proddg/spfileproddg.ora -r physical_standby -a "DATA,OCR"
# 相關引數的意義可以通過srvctl add database -h檢視
 
註冊節點
[oracle@rac1 ~]$ srvctl add instance -d proddg -i proddg1 -n rac1
[oracle@rac1 ~]$ srvctl add instance -d proddg -i proddg2 -n rac2 
 
檢查資源配置
[oracle@rac1 ~]$ srvctl config database -d proddg

檢視資料庫例項是否隨叢集啟動自動啟動
[root@rac1 ~]# crsctl status res ora.proddg.db -p

修改成隨叢集啟動自動啟動
[root@rac1 ~]# crsctl modify res "ora.proddg.db" -attr "AUTO_START=always"

至此,給單例項搭建一個rac dg就已經完成,接下來將介紹如何對其做角色切換

 

五、主從切換準備

23. 主庫新增standby logfile歸檔路徑

[oracle@prod ~]$ mkdir -p /u01/app/oracle/oradata/prod/archstdlog

使用sys資料庫賬號,修改資料庫引數
SQL> alter system set log_archive_dest_2='location=/u01/app/oracle/oradata/prod/archstdlog/ valid_for=(standby_logfiles,standby_role) db_unique_name=prod' sid='*';

 

24. 主庫新增standby logfile

[oracle@prod ~]$ mkdir -p /u01/app/oracle/oradata/prod/standbylog

新增的日誌的大小跟主庫的onlinelog保持一致,數量多兩組(主庫的onlinelog資訊檢視v$log)
SQL> alter database add standby logfile group 21 '/u01/app/oracle/oradata/prod/standbylog/std01.log' size 50M;
SQL> alter database add standby logfile group 22 '/u01/app/oracle/oradata/prod/standbylog/std02.log' size 50M;
SQL> alter database add standby logfile group 23 '/u01/app/oracle/oradata/prod/standbylog/std03.log' size 50M;
SQL> alter database add standby logfile group 24 '/u01/app/oracle/oradata/prod/standbylog/std04.log' size 50M;
SQL> alter database add standby logfile group 25 '/u01/app/oracle/oradata/prod/standbylog/std05.log' size 50M;
SQL> alter database add standby logfile group 26 '/u01/app/oracle/oradata/prod/standbylog/std06.log' size 50M;
SQL> alter database add standby logfile group 27 '/u01/app/oracle/oradata/prod/standbylog/std07.log' size 50M;
SQL> alter database add standby logfile group 28 '/u01/app/oracle/oradata/prod/standbylog/std08.log' size 50M;

 

25. 主庫修改引數檔案

SQL> alter system set standby_file_management=auto sid='*';
SQL> alter system set db_file_name_convert='/u01/app/oracle/oradata/prod/','+DATA/proddg/datafile/' sid='*' scope=spfile;
SQL> alter system set log_file_name_convert='/u01/app/oracle/oradata/prod/','+DATA/proddg/onlinelog/' sid='*' scope=spfile;

到這裡,主庫轉換為備庫的準備工作已完成!

 

26. 從庫配置tnsnames.ora

這裡的配置tnsnames.ora的目的是,當原從庫轉變為新主庫之後,原主庫變為新從庫,新主庫需要給新從庫傳送歸檔日誌,所以這裡的tnsnames要指向新從庫。

[oracle@rac1 ~]$ vi $ORACLE_HOME/network/admin/tnsnames.ora  # rac兩個節點都要設定

toprod =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.56.102)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = prod)
    )
  )


27. 從庫為onlinelog設定歸檔路徑

# 只在節點1設定即可
SQL> alter system set log_archive_dest_1='location=+DATA/proddg/archivelog/ valid_for=(online_logfiles,primary_role) db_unique_name=proddg' sid='*';

 

28. 從庫設定遠端歸檔引數

# 只在節點1設定即可
SQL> alter system set log_archive_dest_3='service=toprod valid_for=(online_logfiles,primary_role) db_unique_name=prod' sid='*';

到這裡,從庫轉為主庫的準備工作已完成!

 

六、主從切換

 

29. 檢視主庫的角色轉換狀態

SQL> select database_role,switchover_status from v$database;

  

30. 主轉從

執行以下命令,將主庫轉為從庫,並且關閉例項
SQL> alter database commit to switchover to physical standby with session shutdown;

 

31. 在從庫節點1上從轉主

由於從庫是叢集,在從轉主的過程中,只能有一個活動節點,因此關閉從庫節點2
SQL> shutdown immediate # 只關閉節點2

SQL> select database_role,switchover_status from v$database;

如果是"NOT ALLOWED"表示歸檔還沒有應用完成,可以等待一段時間

如果日誌全部應用了再檢視角色轉換狀態
SQL> select database_role,switchover_status from v$database;

如果角色轉換狀態是TO PRIMARY,那麼表示可以進行角色轉換

執行從轉主的命令,命令執行成功後,資料庫的狀態會變為mount
SQL> alter database commit to switchover to primary;
SQL> alter database open;

 

32. 開啟新從庫

SQL> startup

應用歸檔
SQL> alter database recover managed standby database using current logfile disconnect from session;

在主庫節點1上切換歸檔
SQL> alter system switch logfile;

 

33. 驗證同步

主庫做修改
SQL> update scott.emp set sal=4000;
SQL> commit;

從庫查詢
SQL> select * from scott.emp;

 

34. 在主庫節點1上為節點2新增日誌檔案

SQL> alter database add logfile thread 2 group 4 '+DATA/proddg/onlinelog/redo04.log' size 50M;
SQL> alter database add logfile thread 2 group 5 '+DATA/proddg/onlinelog/redo05.log' size 50M;
SQL> alter database add logfile thread 2 group 6 '+DATA/proddg/onlinelog/redo06.log' size 50M;
SQL> alter database enable thread 2;

 

35. 啟動新主庫節點2例項

SQL> startup  # 只在節點2上操作

 

36. 錯誤處理

如果發現日誌傳不到備庫的話可以在主庫通過以下命令檢視錯誤原因

SQL> select dest_id,dest_name,log_sequence,status,error from v$archive_dest;

如果報上面的錯誤的話,可以把歸檔開關重啟一下即可
SQL> alter system set log_archive_dest_state_3='defer' sid='*';
SQL> alter system set log_archive_dest_state_3='enable' sid='*';

 

七、總結

1. dg的切換需要停掉所有的應用,並把資料庫的所有連線全部kill掉,賬號全鎖(此舉是為了防止切換過程中有其它使用者登入資料庫),切換完成後再解鎖
2. rac在切換時,只留一個活的例項,其它全部關閉
3. 命令每執行一條,就留意返回的結果,並實時檢視alert.log
4. 由於篇幅限制,文章沒有展示每步執行的結果。所以文章只是提供一個思路,具體步驟還需要根據自己庫的實際情