如要搭配備份/還原裝置使用 Oracle Direct NFS (dNFS),必須符合下列規定:
資料庫伺服器與備份/復原設備之間的網路頻寬足夠
使用所有 Oracle 必要或建議修補程式。Oracle 會在 Oracle 支援文件中維護必要或建議修補程式的清單。
設定管理主控台,透過 dNFS 保護及掛接虛擬 Oracle 資料庫
如要執行以 dNFS 為基礎的備份作業,您必須將備份/復原設備的暫存磁碟格式 (磁碟偏好設定) 設為 NFS。
請按照下列操作說明,將暫存磁碟格式 (磁碟偏好設定) 設為 NFS:
依序前往「管理」>「主機」。
在主機上按一下滑鼠右鍵,然後選取「編輯」。
在暫存磁碟格式中選取「NFS」,然後按一下「儲存」。
在目標主機上執行的動作,讓 dNFS 正常運作
請執行下列動作,確保 dNFS 設定正確無誤:
在「DB Alert.log」下方檢查下列訊息,確認 dNFS 已啟用:
Oracle instance running with ODM: Oracle Direct NFS ODM Library Version 3.01.
如果 dNFS 未啟用,請啟用:
資料庫主機上必須有 NFS 用戶端套件,才能執行保護作業,而且您可能會在任何 Oracle 主機上使用 dNFS 掛接擷取的 Oracle 資料庫,因此這些主機也必須有 NFS 用戶端套件。舉例來說,在 Linux 上,主機應有
nfs-util
套件。請確認下列事項:rpm -qa |grep nfs-util
在 Oracle 主機上啟用 dNFS:
cd $ORACLE_HOME/rdbms/lib make -f ins_rdbms.mk dnfs_on
重新啟動在該
ORACLE_HOME
上執行的資料庫,然後檢查「DB Alert.log」下方是否顯示下列訊息,確認 dNFS 已啟用:使用 ODM 執行的 Oracle 執行個體:Oracle Direct NFS ODM 程式庫 3.0 版
在備份工作期間,執行下列查詢來檢查 dNFS 使用情形:
select * from gv$dnfs_servers;
您可以查看發生 I/O 的 NFS 讀取/寫入統計資料:
select inst_id, PNUM, NFS_READ, NFS_WRITE, NFS_COMMIT, NFS_MOUNT from gv$dnfs_stats where NFS_READ>0 or NFS_WRITE>0 order by inst_id, PNUM;
我們可以查看 dnfs 通道程序資訊。
select c.inst_id, program, pid,pname, local, path from gv$process p, gv$dnfs_channels c where p.inst_id = c.inst_id and c.pnum = p.pid;
排解 dNFS 問題:資料庫問題
包括:
快訊記錄
任何偵錯作業的第一步,都是檢查警示記錄中是否有 dNFS 相關訊息。在 dNFS 資料庫中,常見的問題是通訊端緩衝區大小受限。Oracle 會嘗試調整大小,但這可能會受到作業系統的限制。在此情況下,警示記錄中會發現類似這樣的錯誤:
Direct NFS: Failed to set socket buffer size.wtmax=[1048576]\
rtmax=[1048576], errno=-1
警示記錄中還有其他項目,包括是否使用正確的網路卡與歸檔器通訊。如要判斷是否為這種情況,請查看類似以下的訊息:
Direct NFS: channel id [0] path [192.168.56.3] to filer [192.168.56.3] via local [] is UP
資料庫追蹤記錄檔
如果發生 I/O 問題,可以在資料庫中設定下列事件,擷取額外的記錄資訊。設定這些事件,等待事件發生,然後查看以追蹤檔案。
ALTER SYSTEM SET MAX_DUMP_FILE_SIZE =UNLIMITED;
ALTER SYSTEM SET EVENTS '10298 trace name context forever, level 1'; # KSFD I/O tracing
ALTER SYSTEM SET EVENTS '19392 trace name context forever, level 8'; # kgnfs tracing
ALTER SYSTEM SET EVENTS '19394 trace name context forever, level 8'; # skgnfs tracing
ALTER SYSTEM SET EVENTS '19396 trace name context forever, level 6'; # kgodm tracing
ALTER SYSTEM SET EVENTS '19398 trace name context forever, level 128'; # mount tracing errors
資料庫沒有回應
如果 dNFS 上執行的資料庫沒有回應,請使用 sqlplus 以 SYSDBA 身分登入,然後執行「hanganalyze」或傾印:
```oradebug
oradebug setmypid
oradebug unlimited
oradebug hanganalyze 3
oradebug dump systemstate 266
```
如果資料庫是 RAC 資料庫,請在最後兩個 oradebug 指令中新增 -g 選項。
dNFS 檢視畫面
dNFS 用戶端實際上位於資料庫核心中。因此,資料庫中存在多個 v$ 檢視區塊,可從資料庫內部監控及檢查 dNFS 的健康狀態。Oracle 提供可用於快速監控 dNFS 效能的套件。這個套件位於 Oracle dNFS 監控套件中。
部署完成後,資料庫管理員可以執行下列作業來取得資訊 (參數:dnfs_monitor(睡眠時間)、dnfs_itermonitor(睡眠時間、檢查次數),睡眠時間以秒為單位):
SQL> set serveroutput on
SQL> set lines 200
SQL> exec dnfs_monitor(60);
Started at 01/18/2017 10:09:46 AM
Finished at 01/18/2017 10:10:46 AM
READ IOPS: 2
WRITE IOPS: 3
TOTAL IOPS: 5
READ Throughput: 0 MB/s
WRITE Throughput: 0 MB/s
TOTAL Throughput: 0 MB/s
SQL> exec dnfs_itermonitor(2,10)
Started at 01/18/2017 10:20:18 AM
TIMESTAMP READ IOPS WRITE IOPS TOTAL IOPS READ(MB/s) WRITE (MB/s) TOTAL (MB/s)
01/18/2017 10:20:20 AM 15 7 22 0 0 0
01/18/2017 10:20:22 AM 2 3 5 0 0 0
01/18/2017 10:20:24 AM 0 3 3 0 0 0
01/18/2017 10:20:26 AM 2 2 4 0 0 0
01/18/2017 10:20:28 AM 0 3 3 0 0 0
01/18/2017 10:20:30 AM 2 3 5 0 0 0
01/18/2017 10:20:32 AM 4 3 7 0 0 0
01/18/2017 10:20:34 AM 0 3 3 0 0 0
01/18/2017 10:20:36 AM 2 3 5 0 0 0
01/18/2017 10:20:38 AM 2 3 5 0 0 0
Finished at 01/18/2017 10:20:38 AM
V$ 檢視畫面包括:
V$DNFS_SERVER:顯示所有 NFS 伺服器連線的資訊 (每個 NFS 伺服器各有一個)。「查看」功能可驗證連線和 TCP 通訊端設定。
V$DNFS_CHANNELS:顯示為 NFS 伺服器建立的所有網路路徑資訊。每個 dNFS 用戶端都會為每個程序和每個網路路徑建立一個通道。如果有多個路徑 (多個 NIC),dNFS 用戶端會在所有通道之間進行負載平衡。資料會反映上次選取後的活動。
V$DNFS_FILES:顯示使用 dNFS 用戶端開啟的檔案。
V$DNFS_STAT:dNFS 用戶端的效能指標。
欄 | 說明 |
---|---|
SRVNAME
|
NFS 伺服器名稱 |
DIRNAME
|
NFS 伺服器匯出的磁碟區 |
MNTPORT
|
本機掛接通訊埠 |
NFSPORT
|
NFS 伺服器通訊埠 |
WTMAX
|
NFS 伺服器的寫入大小上限 |
RTMAX
|
NFS 伺服器的讀取大小上限 |
欄 | 說明 |
---|---|
PNUM
|
Oracle 程序編號 (連結至 v$process 中的 PID) |
SVRNAME
|
NFS 伺服器名稱 |
PATH
|
伺服器的網路路徑 |
CH_ID
|
dNFS 管道 ID |
SVR_ID
|
dNFS 伺服器 ID |
SENDS
|
透過管道傳送自上次選取以來執行的作業。 |
RECVS
|
接收自上次選取以來,透過管道進行的作業。 |
PINGS
|
透過管道 自上次選取以來的 Ping 作業。 |
欄 | 說明 |
---|---|
FILENAME
|
檔案名稱。 |
FILESIZE
|
檔案大小。 |
PNUM
|
程序 ID (連結至 v$process 中的 PID) |
SRV_ID
|
NFS 伺服器 ID |
欄 | 說明 |
---|---|
PNUM
|
Oracle 程序編號 (連結至 v$process 中的 PID)
|
NFS_NULL
|
Null operations
|
NFS_GETATTR
|
取得屬性作業 |
NFS_SETATTR
|
設定屬性作業 |
NFS_LOOKUP
|
查詢作業 |
NFS_ACCESS
|
存取作業 |
NFS_READLINK
|
讀取連結作業 |
NFS_READ
|
讀取作業 |
NFS_WRITE
|
寫入作業 |
NFS_CREATE
|
建立作業 |
NFS_MKDIR
|
執行目錄作業 |
NFS_MKNOD
|
執行節點作業 |
NFS_SYMLINK
|
符號連結作業 |
NFS_REMOVE
|
移除作業 |
NFS_RMDIR
|
移除目錄作業 |
NFS_RENAME
|
重新命名作業 |
NFS_LINK
|
連結作業 |
NFS_READDIR
|
讀取目錄作業 |
NFS_READDIRPLUS
|
讀取目錄加號作業 |
NFS_FSSTAT
|
檔案系統狀態作業 |
NFS_FSINFO
|
檔案系統資訊作業 |
NFS_PATHCONF
|
路徑設定作業 |
NFS_COMMIT
|
提交作業 |
NFS_MOUNT
|
掛接作業 |
Oracle dNFS 監控套件
CREATE OR REPLACE PROCEDURE dnfs_monitor
(sleepSecs IN NUMBER)
IS
startTime DATE;
startReadIOPS NUMBER;
startWriteIOPS NUMBER;
startReadBytes NUMBER;
startWriteBytes NUMBER;
endTime DATE;
endReadIOPS NUMBER;
endWriteIOPS NUMBER;
endReadBytes NUMBER;
endWriteBytes NUMBER;
readThr NUMBER;
writeThr NUMBER;
readIOPS NUMBER;
writeIOPS NUMBER;
elapsedTime NUMBER;
BEGIN
SELECT sysdate, SUM(stats.nfs_readbytes), SUM(stats.nfs_writebytes),
SUM(stats.nfs_read), SUM(stats.nfs_write)
INTO startTime, startReadBytes, startWriteBytes, startReadIOPS, startWriteIOPS
FROM dual, v$dnfs_stats stats;
DBMS_OUTPUT.PUT_LINE('Started at ' || TO_CHAR(startTime,'MM/DD/YYYY HH:MI:SS AM'));
DBMS_LOCK.SLEEP(sleepSecs);
SELECT sysdate, SUM(stats.nfs_readbytes), SUM(stats.nfs_writebytes), SUM(stats.nfs_read), SUM(stats.nfs_write)
INTO endTime, endReadBytes, endWriteBytes, endReadIOPS, endWriteIOPS
FROM dual, v$dnfs_stats stats;
DBMS_OUTPUT.PUT_LINE('Finished at ' || to_char(endTime,'MM/DD/YYYY HH:MI:SS AM'));
elapsedTime := (endTime - startTime) * 86400;
readThr := (endReadBytes - startReadBytes)/(1024 * 1024 * elapsedTime);
writeThr := (endWriteBytes - startWriteBytes)/(1024 * 1024 * elapsedTime);
readIOPS := (endReadIOPS - startReadIOPS)/elapsedTime;
writeIOPS := (endWriteIOPS - startWriteIOPS)/elapsedTime;
DBMS_OUTPUT.PUT_LINE('READ IOPS: ' || LPAD(TO_CHAR(readIOPS, '999999999'), 10, ' '));
DBMS_OUTPUT.PUT_LINE('WRITE IOPS: ' || LPAD(TO_CHAR(writeIOPS,
'999999999'), 10, ' '));
DBMS_OUTPUT.PUT_LINE('TOTAL IOPS: ' || LPAD(TO_CHAR(readIOPS + writeIOPS, '999999999'), 10, ' '));
DBMS_OUTPUT.PUT_LINE('READ Throughput: ' || LPAD(TO_CHAR(readThr, '999999999'), 10, ' ') || ' MB/s');
DBMS_OUTPUT.PUT_LINE('WRITE Throughput: ' || LPAD(TO_CHAR(writeThr,
'999999999'), 10, ' ') || ' MB/s');
DBMS_OUTPUT.PUT_LINE('TOTAL Throughput: ' || LPAD(TO_CHAR(readThr + writeThr, '999999999'), 10, ' ') || ' MB/s');
END;
/
CREATE OR REPLACE PROCEDURE dnfs_itermonitor
(sleepSecs IN NUMBER,
iter IN NUMBER)
IS
startTime DATE;
startReadIOPS NUMBER;
startWriteIOPS NUMBER;
startReadBytes NUMBER;
startWriteBytes NUMBER;
endTime DATE;
endReadIOPS NUMBER;
endWriteIOPS NUMBER;
endReadBytes NUMBER;
endWriteBytes NUMBER;
readThr NUMBER;
writeThr NUMBER;
readIOPS NUMBER;
writeIOPS NUMBER;
i NUMBER;
elapsedTime NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE('Started at ' || TO_CHAR(SYSDATE, 'MM/DD/YYYY HH:MI:SS AM'));
DBMS_OUTPUT.PUT_LINE(
LPAD('TIMESTAMP', 15, ' ')||
LPAD('READ IOPS', 33, ' ')||
LPAD('WRITE IOPS', 15, ' ')||
LPAD('TOTAL IOPS', 15, ' ')||
LPAD('READ (MB/s)', 15, ' ')||
LPAD('WRITE (MB/s)', 15, ' ')||
LPAD('TOTAL (MB/s)', 15, ' '));
FOR i IN 1..iter
LOOP
SELECT sysdate, SUM(stats.nfs_readbytes), SUM(stats.nfs_writebytes), SUM(stats.nfs_read), SUM(stats.nfs_write)
INTO startTime, startReadBytes, startWriteBytes, startReadIOPS, startWriteIOPS
FROM dual, v$dnfs_stats stats;
DBMS_LOCK.SLEEP(sleepSecs);
SELECT sysdate, SUM(stats.nfs_readbytes), SUM(stats.nfs_writebytes), SUM(stats.nfs_read), SUM(stats.nfs_write)
INTO endTime, endReadBytes, endWriteBytes, endReadIOPS, endWriteIOPS
FROM dual, v$dnfs_stats stats;
elapsedTime := (endTime - startTime) * 86400;
readThr := (endReadBytes-startReadBytes)/(1024 * 1024 * elapsedTime);
writeThr := (endWriteBytes-startWriteBytes)/(1024 * 1024 * elapsedTime);
readIOPS := (endReadIOPS - startReadIOPS)/elapsedTime;
writeIOPS := (endWriteIOPS - startWriteIOPS)/elapsedTime;
DBMS_OUTPUT.PUT_LINE(
TO_CHAR(endTime, 'MM/DD/YYYY HH:MI:SS AM')||
LPAD(TO_CHAR(readIOPS, '999999999'), 15, '') ||
LPAD(TO_CHAR(writeIOPS, '999999999'), 15,' ') ||
LPAD(TO_CHAR(readIOPS + writeIOPS, '999999999'),15, ' ') ||
LPAD(TO_CHAR(readThr, '999999999'), 15, '') ||LPAD(TO_CHAR(writeThr, '999999999'), 15, '
') ||
LPAD(TO_CHAR(readThr + writeThr, '999999999'), 15, ' '));
END LOOP;
DBMS_OUTPUT.PUT_LINE('Finished at ' || to_char(endTime, 'MM/DD/YYYY HH:MI:SS AM'));
END;
Oracle DBA 指南
- Oracle 資料庫的備份和災難復原
- 保護 Oracle 資料庫的必要條件
- Oracle 修補程式和已知問題
- 準備要保護的 Oracle 資料庫
- 探索及保護 Oracle 資料庫
- Oracle 資料庫的詳細資料和設定
- 搭配備份和災難復原服務使用 dNFS
- 保護已探索到的 Oracle 資料庫
- 將 Oracle 資料庫掛接為標準掛接點
- 建立 Oracle 資料庫的即時虛擬副本
- 還原及復原 Oracle 資料庫
- 使用掛接和遷移功能即時復原 Oracle 資料庫
- 使用備份和災難復原工作流程佈建環境