백업/복구 어플라이언스에서 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 데이터베이스인 경우 마지막 두 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 서버당 하나씩). 보기는 연결 및 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
|
마지막으로 선택한 이후 채널을 통한 핑 작업입니다. |
열 | 설명 |
---|---|
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;