如何實現Oracle數據庫的讀寫分離

在MySQL作爲應用系統的後臺數據庫時,我們常常見到這樣的架構,一拖二、一拖三等等。這是用MySQL的讀寫分離技術,實現數據的寫入和讀取分別在不同的庫上,提升了數據庫服務能力。
同樣,在Oracle作爲後臺數據庫的架構中,我們也可以這麼做。實現的方式有很多種。
有基於RAC架構的,使用其中某個節點作爲讀庫;
有基於Streams數據複製技術的,實時將數據複製到另外一個庫供讀取;
有使用第三方數據複製軟件的,如Golden Gate(已經被Oracle收入囊中)、DSG的,也是實時複製數據到另外一個庫中。
還有使用Logical standby技術,實時複製數據到一個庫,且該庫是對應用而言是隻讀的。
我們這裏介紹最後一個方法,利用dataguard技術中的logical standby實現Oracle數據庫的讀寫分離。

一、創建物理standby

配置主庫(也就是主要執行寫操作的數據庫)的初始化參數

*.log_archive_config='dg_config=(webdb,webdg)'
*.log_archive_dest_2='service=webdb_standby lgwr sync affirm  valid_for=(online_logfiles,primary_role) db_unique_name=webdg'
*.log_archive_dest_state_2='enable'

修改主庫的tnsnames.ora文件

在tnsnames.ora文件中增加一個條目,名稱爲webdb_standby。這個就是log_archive_dest_2中service的名稱。這裏的主庫版本是10g,所以使用LGWR進程將日誌傳輸到備用節點上,而在11g中使用的進程將是LNS。
WEBDB_STANDBY =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.65.3)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = webdb)
    )
  )
 
WEBDB_READER =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.65.3)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = webreader)
    )
  )

配置備用庫(讀庫)的初始化參數

*.db_unique_name='webdg'
*.fal_client='webdb_standby'
*.fal_server='webdb_primary'
*.log_archive_config='dg_config=(webdb,webdg)'
*.log_archive_dest_1='location=+VG2 valid_for=(all_logfiles,all_roles) db_unique_name=webdg'

修改備用庫的tnsnames.ora文件

WEBDB_PRIMARY =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.65.4)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = webdb)
    )
  )
 
 
WEBDB_STANDBY =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.65.3)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = webdb)
    )
  )
在tnsnames.ora文件中增加兩個條目,名稱爲webdb_standby和webdb_primary,分別是fal_client和fal-_server參數對應的值,用於檢測歸檔日誌gap。

備份主庫的數據庫和控制文件

這裏我們可以使用原有的全庫備份,再新備份控制文件用於standby。
Backup current ontrolfile for standby format ‘/u03/webdb_rman/ctl.standby’;

在備用庫上恢復主庫數據文件

restore database;

在備用庫上添加standby logfile

ALTER DATABASE ADD STANDBY LOGFILE group 21 ('+VG2/webdb/standby_redo21.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 22 ('+VG2/webdb/standby_redo22.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 23 ('+VG2/webdb/standby_redo23.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 24 ('+VG2/webdb/standby_redo24.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 25 ('+VG2/webdb/standby_redo25.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 26 ('+VG2/webdb/standby_redo26.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 27 ('+VG2/webdb/standby_redo27.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 28 ('+VG2/webdb/standby_redo28.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 29 ('+VG2/webdb/standby_redo29.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 30 ('+VG2/webdb/standby_redo30.log')  SIZE 52428800 reuse;
ALTER DATABASE ADD STANDBY LOGFILE group 31 ('+VG2/webdb/standby_redo31.log')  SIZE 52428800 reuse;

在備用庫上做恢復操作

recover database;
/u03/webdb_rman@db3=>webdb$rman target /
 
Recovery Manager: Release 10.2.0.4.0 - Production on Mon May 14 10:08:06 2012
 
Copyright (c) 1982, 2007, Oracle.  All rights reserved.
 
connected to target database: WEBDB (DBID=2446281945, not open)
 
RMAN> recover database;
 
Starting recover at 14-MAY-12
using target database control file instead of recovery catalog
allocated channel: ORA_DISK_1
channel ORA_DISK_1: sid=4384 devtype=DISK
 
starting media recovery
恢復出錯後直接退出。

重啓備用庫到實時恢復模式

startup nomount;
alter database mount standby database;
alter database recover managed standby database using current logfile disconnect from session;

檢查主庫上保護模式和保護級別

在主庫上sqlplus中執行下列SQL
select protection_mode,protection_level from v$database;
結果應該是兩個列的值是一致的,纔是正常狀態。
SQL> select protection_mode,protection_level from v$database;
 
PROTECTION_MODE      PROTECTION_LEVEL
-------------------- --------------------
MAXIMUM AVAILABILITY MAXIMUM AVAILABILITY
如果protection_level的值是RESYNCHRONIZATION,如下所示
SQL> select protection_mode,protection_level from v$database;
 
PROTECTION_MODE      PROTECTION_LEVEL
-------------------- --------------------
MAXIMUM AVAILABILITY RESYNCHRONIZATION
這表示DATAGUARD的模式是有問題的,需要解決後才能進行下一步操作。

二、轉換爲邏輯 standby

創建用於讀庫的初始化參數文件和密碼文件

在備用庫的操作系統上$ORACLE_HOME/dbs目錄下,準備兩個文件,分別是邏輯庫webreader的初始化參數文件和密碼文件。
密碼文件orapwwebreader由orapwwebdb直接複製。
初始化參數文件initwebreader.ora從initwebdb.ora複製後做些修改操作,修改的參數項只要是下面列出的這些。
/u01/app/oracle/product/10.2.0/db/dbs@db3=>webreader$more initwebreader.ora
*.audit_file_dest='/u01/app/oracle/admin/webreader/adump'
*.background_dump_dest='/u01/app/oracle/admin/webreader/bdump'
*.core_dump_dest='/u01/app/oracle/admin/webreader/cdump'
*.user_dump_dest='/u01/app/oracle/admin/webreader/udump'
 
*.db_name='webreader'
*.db_unique_name='webdg'
*.fal_client='webdb_reader'
*.fal_server='webdb_primary'
*.log_archive_config='dg_config=(webdb,webdg)'
*.log_archive_dest_1='location=+VG2/ valid_for=(all_logfiles,all_roles) db_unique_name=webdg'

創建用於讀庫的tnsname條目

在備用庫的操作系統上$ORACLE_HOME/network/admin/tnsnames.ora文件中增加一個新的條目webdb_reader。
WEBDB_READER =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.65.3)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = webreader)
    )
  )

增加讀庫的偵聽對象

在備用庫的操作系統上$ORACLE_HOME/network/admin/listener.ora文件中,增加新實例webreader的偵聽對象。
/u01/app/oracle/product/10.2.0/db/network/admin@db3=>webreader$more listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/10.2.0/db/network/admin/listener.ora
# Generated by Oracle configuration tools.
 
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = webdb)
      (ORACLE_HOME = /u01/app/oracle/product/10.2.0/db)
    )
    (SID_DESC =
      (SID_NAME = webdg)
      (ORACLE_HOME = /u01/app/oracle/product/10.2.0/db)
    )
    (SID_DESC =
      (SID_NAME = webreader)
      (ORACLE_HOME = /u01/app/oracle/product/10.2.0/db)
    )
  )
 
LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = db3)(PORT = 1521))
    )
  )

在備用庫上取消恢復管理模式

alter database recover managed standby database cancel ;

在主庫上創建logical standby的數據字典

EXECUTE DBMS_LOGSTDBY.BUILD;
這一步一定要執行成功,並且必須在其他操作之前執行,否則後面執行 alter database recover to logical standby webreader; 會一直等待。
注意:
該過程會自動啓用primary 數據庫的補充日誌(supplemental logging)功能(如果未啓用的話)。
該過程執行需要等待當前所有事務完成,因此如果當前有較長的事務運行,可能該過程執行也需要多花一些等待時間。
該過程是通過閃回查詢的方式來獲取數據字典的一致性,因此oracle 初始化參數UNDO_RETENTION 值需要設置的足夠大。

切換物理Standby爲邏輯Standby

我們將讀庫,也就是logical standby數據庫名稱定義爲webreader。
alter database recover to logical standby webreader;
注意:
這一步很關鍵。如果執行成功了,目標基本就實現了。
但很可能會遇到兩種錯誤。
執行操作一直hang。這是因爲密碼文件中sys密碼不一致,需要建立與主庫一致的密碼文件。
備庫監聽沒有包含standby的實例信息,需要在監聽文件中添加實例信息。在監聽器參數文件的配置中,我們已經添加了所有實例的偵聽信息。即使多加了也不影響監聽器的正常運行。
正常的執行過程應該如下所示:
SQL> alter database recover managed standby database cancel ;
Database altered.
 
SQL> alter database recover to logical standby webreader;
alter database recover to logical standby webreader
*
ERROR at line 1:
ORA-16254: change db_name to WEBREADER in the client-side parameter file (pfile)
ORA-17503: ksfdopn:2 Failed to open file +VG1/webdb/temp01.dbf
ORA-15173: entry 'temp01.dbf' does not exist in directory 'webdb'
這一步執行不成功,也會完成。在關閉打開後可以正常使用。
/u01/home/oracle@db3=>webdb$export ORACLE_SID=webreader
/u01/home/oracle@db3=>webreader$sqlplus / as sysdba
 
SQL*Plus: Release 10.2.0.4.0 - Production on Mon May 14 10:55:53 2012
 
Copyright (c) 1982, 2007, Oracle.  All Rights Reserved.
 
Connected to an idle instance.
 
SQL> startup open
ORACLE instance started.
 
Total System Global Area 5.1540E+10 bytes
Fixed Size                  2179936 bytes
Variable Size            6425676960 bytes
Database Buffers         4.5097E+10 bytes
Redo Buffers               14594048 bytes
Database mounted.
ORA-01589: must use RESETLOGS or NORESETLOGS option for database open
SQL> alter database open resetlogs;
Database altered.
 

備用庫上臨時文件處理

在備用庫上臨時文件需要重建,我選擇新增一個臨時文件。在不同的環境中,臨時文件可能會有很多個。
alter tablespace temp add tempfile '+VG2/webdb/temp02.dbf' size 10240M;

調整主庫上log_archive_dest_2的參數值

在物理standby模式下,這個參數的service值是指向webdb_standby的,現在在邏輯standby模式下,它需要修改爲指向webdb_reader。
alter system set log_archive_dest_2='service=webdb_reader lgwr sync affirm  valid_for=(online_logfiles,primary_role) db_unique_name=webdg';
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章