데이터베이스 연구실.log

RAC의 PDB 운영

PDB의 인스턴스별 OPEN과 SAVE STATE, 파라미터 범위 및 세션 집계

PDB 핫 클론UNPLUGCHECK_PLUG_COMPATIBILITYPDB_PLUG_IN_VIOLATIONSORA-65343KILL SESSION @inst_idORA-00028RACRAC의 PDB 운영

#핵심 요약

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

SQL*Plus (CDB$ROOT, SYSDBA)조회만 함
SELECT inst_id, name, open_mode
FROM gv$pdbs
WHERE name='<PDB_NAME>'
ORDER BY inst_id;

결과 해석: 실습 두 노드 예시는 한 인스턴스의 READ WRITE를 유지하면서 다른 인스턴스의 MOUNTED를 READ WRITE로 바꿈

SQL*Plus (CDB$ROOT, SYSDBA)객체 또는 설정을 변경함
ALTER PLUGGABLE DATABASE <PDB_NAME> OPEN INSTANCES=ALL EXCEPT ('<INSTANCE>');
ALTER PLUGGABLE DATABASE <PDB_NAME> SAVE STATE INSTANCES=ALL;

결과 해석: 수업 자료에는 재기동 뒤 양쪽 READ WRITE라는 기록이 있음

SQL*Plus (CDB$ROOT, SYSDBA)조회만 함
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 생성 직후와 인스턴스별 열기

SQL*Plus (1번 노드, CDB$ROOT SYSDBA)객체 또는 설정을 변경함
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 세션만)
SQL*Plus (<NODE1> SYSDBA, CDB$ROOT)인스턴스 또는 서비스 중단이 필요함
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>에서도 접속됨

SQL*Plus (<NODE1> SYSDBA, CDB$ROOT)조회만 함
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/
SQL*Plus (CDB$ROOT SYSDBA)조회만 함
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;
grid 계정 셸 (ORACLE_SID=+ASM1)조회만 함
asmcmd ls +DATA/<DB_NAME>/
asmcmd ls +DATA/<DB_NAME>/<PDB_GUID>/DATAFILE/
SQL*Plus (PDB, SYSDBA)객체 또는 설정을 변경함
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 파일까지 지우므로 실습용인지 확인한 뒤 실행함

#핫 클론과 언플러그, 플러그인

SQL*Plus (1번 노드, CDB$ROOT SYSDBA)데이터 또는 파일을 삭제함, 되돌릴 수 없음
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;
OS 셸 (oracle 사용자, 1번 노드)객체 또는 설정을 변경함
scp /home/oracle/pdb_test.pdb oracle@<NODE2>:/home/oracle/
SQL*Plus (2번 노드, CDB$ROOT SYSDBA)객체 또는 설정을 변경함
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 자원 이름 검색이 빈 결과라는 이유만으로 서비스 관리 방식을 입증할 수는 없음

SEO_HKabsumveritas@gmail.comBuilt with Claude Code & Codex

마지막 갱신 개인 학습 기록이며 운영 환경 적용 전 공식 문서 확인 필요

두 글자 이상 입력, 위아래 화살표로 이동하고 Enter로 열기