Oracle 43일차

[리스너]

외부 접속을 가능하게 하는 프로세스.
여러 리스너 구성 가능 (네트워크 부하 분산).
정적/동적 구성.
리스너는 netca, netmgr 등으로 추가/삭제/변경 가능.

** 정적 구성과 동적 구성
* 정적 구성
– 리스너가 수동으로 명시된 서비스를 연결.
– local_listener 설정 필요 없음.

SID_LIST_LISTENER3 =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = db1)
      (GLOBAL_DBNAME = db1)
      (ORACLE_HOME = /oracle12/app/oracle/product/12.2.0.1/db_1)
    )
  )

* 동적 구성
– 리스너가 자동으로 서비스를 연결.
– local_listener 설정 필요.
– listener.ora 파일에 아래와 같이 등록

리스너명 =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )

[실습 – 동적 리스너 추가 (netca)]

-- Xmanager passive 실행 후

export DISPLAY=192.168.13.16:0.0
-- 본인 windows IPv4주소 + Xmanager가 지정한 번호(0.0)

export LANG=C

netca

* netca GUI 창에서 선택

  1. listener config
  2. add
  3. LISTENER2
  4. next
  5. use another port number : 1522
  6. no -> next
  7. finish

이러면 추가 완료.

cat /oracle12/app/oracle/product/12.2.0.1/db_1/network/admin/listener.ora
---- 출력 ----
LISTENER2 =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1522))
    )
  )

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1521))
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
    )
  )

* listener start/status/stop 방법

lsnrctl start LISTENER2
lsnrctl status LISTENER2
lsnrctl stop LISTENER2

* listener 상태 확인

lsnrctl status LISTENER2
-- 아무리 기다려도 물지를 않는다.
-- 로컬 리스너 설정이 안되어있어서

* 로컬 리스너 설정 (tns alias를 사용한 등록 방식)

> show parameter local_listener
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
local_listener                       string      LISTENER_DB1
-- tnsnames.ora 수정 - alias 설정
$ vi tnsnames.ora
LISTENER_DB2 =
  (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1522))
-- 추가해주기
-- 로컬 리스너 추가
> alter system set local_listener = LISTENER_DB1, LISTENER_DB2 scope = both;

> show parameter local_listener
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
local_listener                       string      LISTENER_DB1, LISTENER_DB2

$ lsnrctl status LISTENER2
---- 출력 ----
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=oel7)(PORT=1522)))
Services Summary...
Service "db1" has 1 instance(s).
  Instance "db1", status READY, has 1 handler(s) for this service...
Service "db1XDB" has 1 instance(s).
  Instance "db1", status READY, has 1 handler(s) for this service...
The command completed successfully

* WINDOWS쪽의 tnsnames.ora 수정

DB1_1522 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172.16.124.128)(PORT = 1522))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = db1)
    )
  )
-- 추가해주기
-- 이제 오렌지에서 DB1_1522라는 이름으로 1522번 포트 통해서 LISTENER2를 통한 접속이 가능함.

[실습 – 동적 리스너 추가 (listener.ora 직접)]

굳이 netca를 사용해서 리스너 추가할 필요가 없네.
그냥 listener.ora->tnsnames.ora->DB alter system set local_listener->windows tnsnames.ora 이러면 됨.

* listener.ora 수정

vi listener.ora
---- 추가 ----
LISTENER3 =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1523))
    )
  )

* lsnrctl start LISTENER3

* 로컬 리스너 설정(tns alias)

vi tnsnames.ora
---- 추가 ----
LISTENER_DB3 =
  (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1523))

* DB쪽 parameter 수정

> alter system set local_listener = LISTENER_DB1, LISTENER_DB2, LISTENER_DB3 scope=both;
-- 이걸 치면 LISTENER3이 서비스를 물어서 status 쳤을 때 Summary가 뜸.
-- 그 전까진 못 물어서 no service 라고 뜸.

* windows 쪽의 tnsnames.ora 수정

DB1_1523 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172.16.124.128)(PORT = 1523))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = db1)
    )
  )

[실습 – 동적 리스너 추가 (tnsnames.ora 사용X)]

* listener.ora 추가

vi listener.ora
---- 추가 ----
LISTENER4 =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1524))
    )
  )

* DB local_listener 등록

-- tnsnames.ora에 있는 orcl에 있는 DESCRIPTION 가져와서 수정.
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oel7)(PORT=1524)))

-- DB local_listener 수정
> alter system set local_listener = LISTENER_DB1,LISTENER_DB2,LISTENER_DB3,'(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=oel7)(PORT=1524)))' scope=both;

* WINDOWS쪽 tnsnames.ora 수정

DB1_1524 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 172.16.124.128)(PORT = 1524))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = db1)
    )
  )

[실습 – 정적 리스너 추가 (listener.ora 직접 수정)]

* listener.ora 수정

LISTENER5 =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS = (PROTOCOL = TCP)(HOST = oel7)(PORT = 1525))
    )
  )
SID_LIST_LISTENER5 =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = db1)
      (GLOBAL_DBNAME = db1)
      (ORACLE_HOME = /oracle12/app/oracle/product/12.2.0.1/db_1)
    )
  )

* lsnrtctl start LISTENER5
이 경우에는 서비스를 물려고 대기하는 시간이 없이 바로 문다.
– 정적 리스너는 LREG를 안 거치기 때문에 SID_LIST를 꼭 지정해줘야 한다.
SID_LIST를 지정을 해줬기 때문에 LREG프로세스를 거치지 않고 바로 DB에 연결할 수 있다.
– 동적 리스너의 경우에는 SID_LIST지정이 필요 없지만 대신 LREG 프로세스가 알아서 인스턴스 상태 확인해서 연결해준다.

-- 정적 리스너의 status 출력 결과는 UNKNOWN으로 뜬다.
-- 인스턴스가 online인지 신경안쓰고 냅다 물었다는 뜻.
-- 그래서 DB offline이어도 똑같이 UNKNOWN이라고 뜸.
Service "db1" has 1 instance(s).
  Instance "db1", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully

-- 동적 리스너의 status 출력 결과는 READY로 뜬다.
-- 인스턴스가 online인지 확인하고 물었다는 뜻.
-- offline이면 no services가 뜸.
Service "db1" has 1 instance(s).
  Instance "db1", status READY, has 1 handler(s) for this service...
Service "db1XDB" has 1 instance(s).
  Instance "db1", status READY, has 1 handler(s) for this service...
The command completed successfully

[DB recovery에 대한 의견]

current redo log file이 날아가면 불완전 복구밖에 안되기 때문에 redo log file이 가장 중요하다. controlfile은 script로 재생성이 가능하고, datafile은 hot backup본과 archive log file을 통해서 recover가 가능하다. 따라서 redo log file 멤버의 다중화 구성(저장 경로 물리적으로 분리)을 통해서 current redo log file이 날아가는 것을 방지하는 게 중요하다.

[실습 – drop tablespace]

drop tablespace 시 해당 tablespace 내의 모든 테이블이 삭제됨.
recyclebin에 남지 않고 flashback table level 복구 불가.

사전 작업 (상황 설정 과정)

-- 1. tablespace 생성
select tablespace_name, file_name
from dba_data_files;

create tablespace test01 datafile '/home/oracle/oradata/db1/test01.dbf' size 200m;

-- 2. table 생성
create table system.recover_test11(no number) tablespace test01;
insert into system.recover_test11 values(1);
insert into system.recover_test11 values(2);
insert into system.recover_test11 values(3);
commit;

-- 3. offline full backup 받기
> shutdown immediate
$ data
$ cp * /oracle12/backup/cold_backup

-- 4. DB 기동
> startup

-- 5. log switch 3번 이상
> alter system switch logfile;

-- 6. 시점 확인
select sysdate from dual;
-- 2024/12/11 15:57:59

-- 7. drop tablespace (장애 발생)
drop tablespace test01 including contents and datafiles;

-- 8. log switch 3번 이상
> alter system switch logfile;

-- 9. 데이터 조회 시도
select * from system.recover_test11;  -- 존재하지 않습니다.

복구 과정

-- 1. DB shutdown
> shutdown immediate
-- abort도 상관 없긴 한데 immediate가 되면 하자.

-- 2. datafile restore
$ cp /oracle12/backup/cold_backup/*.dbf /home/oracle/oradata/db1

-- 3. mount
> startup mount

-- 4. recover
-- 날라간 tablespace를 복구하는 게 목표니깐 불완전 복구가 필요함.
-- 완전 복구하면 tablespace 날라간 채로 복구되는거임.
> recover database until time '2024/12/11 15:57:59'

-- 5. DB open
> alter database open resetlogs;

-- 6. 데이터 조회 시도
> select * from system.recover_test11
                     *
ERROR at line 1:
ORA-00376: file 2 cannot be read at this time
ORA-01111: name for data file 2 is unknown - rename to correct file
ORA-01110: data file 2:
'/oracle12/app/oracle/product/12.2.0.1/db_1/dbs/MISSING00002'

-- 7. controlfile 상의 datafile 정보 확인
select name, status
from v$datafile;
---- 출력 ----
/home/oracle/oradata/db1/system01.dbf	SYSTEM
/oracle12/app/oracle/product/12.2.0.1/db_1/dbs/MISSING00002	RECOVER
/home/oracle/oradata/db1/sysaux01.dbf	ONLINE
/home/oracle/oradata/db1/undotbs01.dbf	ONLINE
/home/oracle/oradata/db1/users01.dbf	ONLINE
-- MISSING00002 라는 임시 datafile이 recover 상태로 확인됨.
-- controlfile의 정보와 archive file의 정보가 일치하지 않는데 복구 과정에서 써야된다고 하니깐 임시 파일에다가 쓴거임.

-- 8. file rename (media 정보 일치를 위해 필요)
> alter database rename file '/oracle12/app/oracle/product/12.2.0.1/db_1/dbs/MISSING00002' to '/home/oracle/oradata/db1/test01.dbf';

-- 9. recover datafile
> recover datafile '/home/oracle/oradata/db1/test01.dbf'

-- 10. tablespace online
> alter tablespace test01 online;

-- 11. 데이터 조회
> select * from system.recover_test11;
-- 1,2,3 다 잘 나옴.

Leave a Comment