バックアップ/リカバリ アプライアンスで 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 クライアント パッケージは、保護ジョブのデータベース ホストと、dNFS を使用してキャプチャされた Oracle データベースをマウントする可能性のある Oracle ホストに存在する必要があります。たとえば、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 はサイズを調整しようとしますが、O/S によって制限される場合があります。この場合、アラートログに次のようなエラーが見つかります。
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 データベースの場合は、最後の 2 つの oradebug コマンドに -g オプションを追加します。
dNFS ビュー
dNFS クライアントは実際にはデータベース カーネル内にあります。そのため、データベース内には、データベース内から dNFS の健全性をモニタリングして確認するための v$ ビューがいくつかあります。Oracle には、dNFS のパフォーマンスをすばやくモニタリングできるパッケージが用意されています。このパッケージは、Oracle dNFS モニタ パッケージにあります。
デプロイ後、DBA は次のように実行して情報を取得できます(パラメータ: 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 サーバーごとに 1 つ)の情報が表示されます。ビューは、接続と TCP ソケットの設定を確認する場合に便利です。
V$DNFS_CHANNELS: NFS サーバーに作成されたすべてのネットワーク パスの情報が表示されます。各 dNFS クライアントは、ネットワーク パスごとにプロセスごとに 1 つのチャネルを作成します。複数のパスが存在する場合(複数の 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
|
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;