RAC의 PDB 운영
PDB의 인스턴스별 OPEN과 SAVE STATE, 파라미터 범위 및 세션 집계
#핵심 요약
PDB 데이터 파일을 공유해도 OPEN_MODE는 인스턴스마다 다를 수 있음
SAVE STATE는 지정 인스턴스가 재기동된 뒤 PDB의 OPEN 상태를 복원하는 설정임
장애 시 서비스 이동은 별도 기능임
세션을 노드, PDB별로 집계할 때 INST_ID와 CON_ID를 함께 사용함
#개념과 동작 원리
| 항목 | 설명 |
|---|---|
| INSTANCES 지정 | 특정 인스턴스 또는 ALL EXCEPT로 OPEN 대상 선택 |
| SAVE STATE | 인스턴스별 OPEN 상태 저장 |
| DISCARD STATE | 저장 상태 제거이며 현재 PDB를 즉시 닫는 명령은 아님 |
| PDB 연결 서비스 | 기동 노드에서 닫힌 PDB를 READ WRITE로 여는 방식 |
| PDB 파라미터 | PDB 영구 설정과 CDB 공유 SPFILE을 구분 |
| SID='*'와 개별 SID | 공통값보다 해당 인스턴스 전용값 우선 |
PDB에서 바꿀 수 있는 파라미터는 ISPDB_MODIFIABLE로 확인하며 SCOPE=SPFILE 변경은 즉시 메모리에 반영되지 않음
실습의 PDB_SPFILE$는 내부 테이블 조회 예시임
아래 SQL은 공개 뷰에서 파라미터 변경 가능 여부를 조회함
#필수 명령어 또는 SQL
SELECT inst_id, name, open_mode
FROM gv$pdbs
WHERE name='<PDB_NAME>'
ORDER BY inst_id;결과 해석: 실습 두 노드 예시는 한 인스턴스의 READ WRITE를 유지하면서 다른 인스턴스의 MOUNTED를 READ WRITE로 바꿈
ALTER PLUGGABLE DATABASE <PDB_NAME> OPEN INSTANCES=ALL EXCEPT ('<INSTANCE>');
ALTER PLUGGABLE DATABASE <PDB_NAME> SAVE STATE INSTANCES=ALL;결과 해석: 수업 자료에는 재기동 뒤 양쪽 READ WRITE라는 기록이 있음
SELECT name, ispdb_modifiable
FROM v$system_parameter
WHERE name IN ('optimizer_index_cost_adj', 'open_cursors', 'processes')
ORDER BY name;
SELECT s.inst_id, c.name AS pdb_name, COUNT(*) AS sessions
FROM gv$session s, gv$containers c
WHERE s.inst_id = c.inst_id
AND s.con_id = c.con_id
AND s.type = 'USER'
GROUP BY s.inst_id, c.name
ORDER BY s.inst_id, c.name;결과 해석: TRUE인 파라미터가 PDB 수준 변경 대상이며 세션 집계는 노드, 컨테이너별 일반 사용자 세션을 셈 실제 집계 결과 행은 기재 없음
#PDB 생성 직후와 인스턴스별 열기
SHOW PARAMETER db_create_file_dest
CREATE PLUGGABLE DATABASE <PDB_NAME> ADMIN USER pdbadmin IDENTIFIED BY "<PASSWORD>";
SELECT inst_id, name, open_mode FROM gv$pdbs WHERE name = '<PDB_NAME>' ORDER BY inst_id;
ALTER PLUGGABLE DATABASE <PDB_NAME> OPEN INSTANCES = ALL;
SELECT con_name, instance_name, state FROM dba_pdb_saved_states;결과 해석:
실습 기록: OMF(+DATA)로 만든 직후에는 만든 노드를 포함해 두 인스턴스 모두 MOUNTED였고, OPEN INSTANCES = ALL 뒤 둘 다 READ WRITE였음
2번 노드에서 PDB에 만든 테이블 10건이 1번 노드에서도 그대로 보였음
INSTANCES를 생략하면 명령을 실행한 인스턴스만 바뀌고, PDB는 공유 CDB에 한 번만 만들므로 다른 노드에서 CREATE를 반복하지 않음
OPEN INSTANCES = ('<INSTANCE1>')로 한 노드만 열면 다른 노드는 MOUNTED로 남고, SAVE STATE INSTANCES = ('<INSTANCE1>') 뒤 DBA_PDB_SAVED_STATES에 그 인스턴스의 OPEN이 기록돼 srvctl로 DB를 다시 띄워도 1번 READ WRITE, 2번 MOUNTED로 돌아왔음
#다른 노드의 PDB 세션 종료
| 구분 | non-CDB RAC | CDB RAC |
|---|---|---|
| 세션을 찾는 좌표 | INST_ID, SID, SERIAL# | INST_ID, CON_ID, SID, SERIAL# |
| KILL을 실행하는 곳 | 아무 인스턴스 | 루트(모든 컨테이너) 또는 해당 PDB 안(그 PDB 세션만) |
SELECT inst_id, con_id, sid, serial#, username, status
FROM gv$session WHERE username = '<USERNAME>';
SELECT con_id, name FROM v$pdbs;
ALTER SYSTEM KILL SESSION '<SID>,<SERIAL#>,@2' IMMEDIATE;결과 해석:
인스턴스마다 같은 SID가 있을 수 있어 @inst_id로 세션이 속한 인스턴스를 지정함<NODE1>에서 실행해도 @2면 <NODE2>의 세션이 끊김
실습 기록: <NODE2> VIP로 PDB 로컬 사용자에 접속한 세션을 <NODE1> 루트에서 끊자 재조회가 no rows selected였고, 끊긴 세션에서 SQL을 실행하면 ORA-00028: your session has been killed가 났음
ALTER SESSION SET CONTAINER = <PDB_NAME> 뒤 GV$SESSION을 보면 그 PDB 세션만 보이고, PDB 안에서는 그 PDB 세션만 끊을 수 있음
PDB에 만든 로컬 사용자는 c## 접두어가 필요 없고, 데이터 사전을 공유하므로 <NODE1>에서 만든 계정으로 <NODE2>에서도 접속됨
SELECT 'ALTER SYSTEM KILL SESSION ''' || sid || ',' || serial# || ',@' || inst_id || ''' IMMEDIATE;'
FROM gv$session
WHERE con_id = (SELECT con_id FROM v$pdbs WHERE name = '<PDB_NAME>')
AND type = 'USER';결과 해석: 패치 전에 한 PDB의 업무 세션만 노드와 관계없이 끊을 KILL 문을 만듦
루트와 다른 PDB 세션은 CON_ID와 TYPE = 'USER' 조건으로 제외되며, 실습에서는 <NODE2>에 남겨 둔 루트 SYSDBA 세션이 계속 동작하는지로 확인했음
노드별, PDB별 세션 수 집계 쿼리는 위 절에 있음
#PDB 데이터 파일과 ASM 경로
| 컨테이너 | ASM 경로 예 |
|---|---|
| CDB$ROOT | +DATA/<DB_NAME>/DATAFILE/ |
| PDB | +DATA/<DB_NAME>/<PDB_GUID>/DATAFILE/ |
SELECT con_id, name, guid FROM v$pdbs WHERE name = '<PDB_NAME>';
SELECT con_id, file#, name FROM v$datafile ORDER BY con_id, file#;
SELECT d.file_name, d.bytes / 1024 / 1024 AS mb
FROM cdb_data_files d JOIN v$pdbs p ON d.con_id = p.con_id
WHERE p.name = '<PDB_NAME>'
ORDER BY d.file_name;asmcmd ls +DATA/<DB_NAME>/
asmcmd ls +DATA/<DB_NAME>/<PDB_GUID>/DATAFILE/SHOW PARAMETER db_create_file_dest
CREATE TABLESPACE ts_pdb1 DATAFILE SIZE 50M; -- 1번 노드
ALTER TABLESPACE ts_pdb1 ADD DATAFILE SIZE 50M; -- 2번 노드
ALTER DATABASE DATAFILE '<ADDED_FILE_NAME>' RESIZE 100M;결과 해석:
db_create_file_dest가 +DATA면 파일 이름 없이 만들 수 있고(OMF), PDB 파일은 PDB GUID 디렉터리 아래에 생김
한 노드에서 만들거나 늘린 파일이 다른 노드의 DBA_DATA_FILES에 같은 이름과 크기로 보이는지 비교함
정리용 DROP TABLESPACE ts_pdb1 INCLUDING CONTENTS AND DATAFILES는 ASM 파일까지 지우므로 실습용인지 확인한 뒤 실행함
#핫 클론과 언플러그, 플러그인
SELECT property_value FROM database_properties WHERE property_name = 'LOCAL_UNDO_ENABLED';
CREATE PLUGGABLE DATABASE pdb_test FROM <PDB_NAME>;
ALTER PLUGGABLE DATABASE pdb_test OPEN INSTANCES = ALL;
ALTER PLUGGABLE DATABASE pdb_test CLOSE IMMEDIATE INSTANCES = ALL;
ALTER PLUGGABLE DATABASE pdb_test UNPLUG INTO '/home/oracle/pdb_test.pdb';
DROP PLUGGABLE DATABASE pdb_test INCLUDING DATAFILES;scp /home/oracle/pdb_test.pdb oracle@<NODE2>:/home/oracle/SET SERVEROUTPUT ON
BEGIN
IF DBMS_PDB.CHECK_PLUG_COMPATIBILITY('/home/oracle/pdb_test.pdb', 'PDB_TEST') THEN
DBMS_OUTPUT.PUT_LINE('YES');
ELSE
DBMS_OUTPUT.PUT_LINE('NO');
END IF;
END;
/
CREATE PLUGGABLE DATABASE pdb_test USING '/home/oracle/pdb_test.pdb';
ALTER PLUGGABLE DATABASE pdb_test OPEN INSTANCES = ALL;
SELECT name, cause, message, status FROM pdb_plug_in_violations WHERE name = 'PDB_TEST';결과 해석:
| 작업 | 단일 인스턴스 | RAC |
|---|---|---|
| 클론 뒤 열기 | OPEN |
OPEN INSTANCES = ALL |
| 언플러그 전 | CLOSE |
CLOSE IMMEDIATE INSTANCES = ALL, 하나라도 열려 있으면 ORA-65025 |
| XML, .pdb 위치 | 로컬 디스크 | 작업한 노드의 로컬 디스크, 다른 노드나 서버에서 쓰려면 복사 |
| 다른 서버로 이동 | XML + 데이터 파일 복사 또는 .pdb | 데이터 파일이 ASM에 있어 .pdb 아카이브가 간편 |
로컬 UNDO가 TRUE면 소스 PDB를 연 채로 복제(핫 클론)할 수 있고, 새 인스턴스나 SGA를 만들 필요가 없음
수업 자료는 non-CDB 시절 RMAN DUPLICATE, Data Pump, TTS로 하던 복제, 이관, DB별 반복 패치를 PDB 단위 클론과 언플러그, 플러그인으로 줄인다고 설명함
.pdb 아카이브는 XML과 데이터 파일 복사본을 한 파일로 묶으므로 만든 뒤에는 소스 PDB를 INCLUDING DATAFILES로 지워도 다시 플러그인할 수 있음
XML 방식은 데이터 파일을 옮기지 않으므로, 등록만 지울 때는 반드시 KEEP DATAFILES를 씀
이미 언플러그한 PDB(STATUS = UNPLUGGED)를 다른 형식으로 다시 언플러그하면 ORA-65343이 남
실습은 DROP ... KEEP DATAFILES, CREATE ... USING '<xml>' NOCOPY로 다시 꽂고 열었다 닫은 뒤 .pdb로 언플러그했음
.pdb를 플러그인하면 데이터 파일이 db_create_file_dest에 새로 만들어지고, 이 값이 없으면 FILE_NAME_CONVERT로 위치를 정함
PDB_PLUG_IN_VIOLATIONS에 STATUS = PENDING인 ERROR가 남으면 PDB가 RESTRICTED로 열릴 수 있음
실습은 CDB 하나에서 소스 PDB 삭제와 2번 노드 플러그인으로 다른 CDB로의 이관을 흉내 낸 것임
#사용 조건과 주의사항
생성한 KILL 문은 대상이 맞는지 확인한 뒤 실행하고, 실행 뒤 같은 조건으로 다시 조회함 PDB 자원 이름 검색이 빈 결과라는 이유만으로 서비스 관리 방식을 입증할 수는 없음