모니터링 연결과 계정
모니터 전용 조회 계정과 권한, 포트와 리스너 및 DSN 연결 준비, 다른 계정 세션의 조회 점검
#핵심 요약
실습 모니터는 SYS나 postgres(슈퍼유저)로 모니터링하지 않고, 조회 권한만 가진 전용 계정을 만듦
Oracle 전용 계정에는 CREATE SESSION, SELECT_CATALOG_ROLE, SELECT ANY DICTIONARY 세 가지만 줌
데이터 변경 권한은 없음
PostgreSQL 전용 계정에는 pg_monitor(모든 사용자의 세션, 대기, 로그 폴더 조회), pg_read_all_data(EXPLAIN을 위한 테이블 읽기), pg_read_file 실행 권한(서버 로그 읽기)을 줌
확인 기준은 전용 계정으로 자기 세션이 아니라 다른 사용자의 세션과 SQL이 보이는가임
#개념과 동작 원리
#연결 준비 순서(Oracle)
| 순서 | 연결 점검 항목 | 실습 오류와 조치 |
|---|---|---|
| 1 | PC에서 DB 서버 1521 포트 접속 | 핑은 되고 1521만 실패 → 서버는 살아 있고 리스너나 방화벽 문제 |
| 2 | 서버 IP, 리스너 상태 | TNS-12541: no listener → lsnrctl start |
| 3 | 서비스 등록 | 막 띄운 리스너는 서비스를 모른다 → alter system register; |
| 4 | 방화벽 1521/tcp | 실습에서는 이미 열려 있었음 |
| 5 | Python 접속 시험 | 접속 성공, CDB = NO |
| 6 | 프로그램의 기본 DSN | app.py의 MON_DSN, load.py, bad_sql.py의 LOAD_DSN 기본값을 실제 값으로 |
실습 DB는 non-CDB라서 서비스 이름이 하나이고, 모니터링, 부하 테스트, 악성 SQL을 모두 같은 DB에서 했음
DSN은 환경 변수로 주면 코드를 고치지 않아도 됨
#필수 명령어 또는 SQL
#Oracle 전용 계정(non-CDB용 스크립트)
create user <MONITOR_USER> identified by <PASSWORD>;
-- ※ SQL*Plus 는 ';' 뒤에 주석이 붙으면 문장이 끝난 줄로 보지 않으므로 주석은 윗줄에 쓴다
grant create session to <MONITOR_USER>;
-- V$ 뷰, DBA_ 뷰 조회
grant select_catalog_role to <MONITOR_USER>;
-- 일부 X$ 기반 V$ 뷰 대비
grant select any dictionary to <MONITOR_USER>;결과 해석: User created. 뒤에 Grant succeeded.가 세 번 나와야 함
실습 스크립트는 이어서 새 계정으로 접속해 v$session 건수와 v$instance를 조회해 V$ 뷰가 보이는지 바로 확인함
select privilege from dba_sys_privs where grantee = '<MONITOR_USER>';
select granted_role from dba_role_privs where grantee = '<MONITOR_USER>';결과 해석: 첫 조회에 CREATE SESSION, SELECT ANY DICTIONARY, 둘째 조회에 SELECT_CATALOG_ROLE이 나오면 권한이 들어간 것임
권한 조회 일반은 권한을 봄
#PostgreSQL 전용 계정
create role <MONITOR_USER> login password '<PASSWORD>';
grant pg_monitor to <MONITOR_USER>;
grant pg_read_all_data to <MONITOR_USER>;
grant execute on function pg_read_file(text, bigint, bigint) to <MONITOR_USER>;sudo -u postgres psql -f 01_create_monitor_user.sql결과 해석: GRANT ROLE 두 번과 GRANT 한 번이 나오고, 확인 조회의 has_pg_monitor가 t여야 함
실습에서는 pg_monitor를 PostgreSQL 10 이상, pg_read_all_data를 14 이상의 기본 롤이라고 주석에 적었음
서버 로그 파일 읽기는 실습용이며 운영에서는 로그 수집 도구를 쓴다고 주석에 있음
#다른 사용자의 세션이 보이는지(Oracle 확인 스크립트)
import oracledb
DSN = "<HOST>:1521/<SERVICE_NAME>"
other = oracledb.connect(user="<USERNAME>", password="<PASSWORD>", dsn=DSN)
other.module = "CHECK-OTHER-SESSION"
other.cursor().execute("select 1 from dual") # module 값이 서버에 전달되도록 한 번 호출
mon = oracledb.connect(user="<MONITOR_USER>", password="<PASSWORD>", dsn=DSN)
cur = mon.cursor()
cur.execute("""select sid, serial#, con_id, username, status, module
from v$session
where type = 'USER'
order by sid""")
for sid, serial, con_id, user, status, module in cur:
print(sid, serial, con_id, user, status, module)
other.close()
mon.close()결과 해석: 다른 계정으로 연 세션이 MODULE CHECK-OTHER-SESSION으로 보이면 권한이 제대로 들어간 것임
non-CDB의 CON_ID는 항상 0이고 CDB라면 PDB 세션은 3 이상으로 보인다고 실습에서는 적었음
PostgreSQL판 확인 스크립트도 같은 방식임
부하용 계정으로 세션을 열고 SQL을 한 번 실행해 둔 뒤 전용 계정으로 pg_stat_activity(backend_type = 'client backend')를 조회하고, pg_ls_logdir()로 최근 로그 파일을 봄
다른 세션의 QUERY가 <insufficient privilege>가 아니라 실제 SQL로 보여야 함
#PC에서 PostgreSQL 접속 준비 (PG 게이지 1단계)
PG 게이지는 오라클 게이지와 화면, 동작이 같고 V$ 뷰 대신 pg_stat_activity, pg_stat_database 같은 통계 뷰를 읽으며, DB 재시작이 필요한 확장(pg_stat_statements)은 쓰지 않음
cd /d "<WORK_DIR>"
pip install -r requirements.txt결과 해석:
패키지 설치는 Anaconda Prompt에서, TCP 연결 검사는 PowerShell에서 실행함
Test-NetConnection <VM_IP> -Port 5432cd /tmp
hostname -I
systemctl is-active postgresql-15
sudo -u postgres psql -c "show listen_addresses" -c "show port"
sudo -u postgres psql -c "select type, database, user_name, address, auth_method from pg_hba_file_rules"
sudo firewall-cmd --list-ports결과 해석:
아나콘다는 PATH에 등록되지 않으므로 python, pip은 일반 명령 프롬프트가 아니라 Anaconda Prompt에서 실행함
실습 기록: Anaconda 2026.07의 파이썬 3.14.6에서도 psycopg 3.3.6이 설치됨
sudo -u postgres psql은 /tmp에서 실행해야 postgres 계정이 oracle 홈 디렉터리에 들어가지 못해 나는 경고가 없음
실습 기록: listen_addresses = *, 포트 5432, pg_hba_file_rules에 local ... peer와 host all all 0.0.0.0 scram-sha-256(넷마스크는 address 열에 안 보임), 방화벽에 5432/tcp가 열려 있고 PC에서 TcpTestSucceeded : True
local ... peer는 VM 안에서 OS 계정 이름으로 비밀번호 없이 접속하는 규칙이고, host ... scram-sha-256은 바깥에서 비밀번호로 접속하는 규칙임
TcpTestSucceeded : False일 때 |
조치 |
|---|---|
listen_addresses가 localhost |
postgresql.conf에서 '*'로 바꾸고 재시작 |
| 외부 주소 규칙 없음 | pg_hba.conf에 host all all 0.0.0.0/0 scram-sha-256을 넣고 select pg_reload_conf(); |
| 방화벽 | sudo firewall-cmd --add-port=5432/tcp --permanent; sudo firewall-cmd --reload |
0.0.0.0/0은 모든 주소에서 비밀번호 접속을 허용하므로 실습 VM이 아닌 곳에서는 접속할 PC 대역으로 좁힘
#사용 조건과 주의사항
실습의 CDB용 계정 스크립트는 non-CDB에서 ORA-65090, ORA-65117, ORA-00922로 실패했음ALTER SESSION SET CONTAINER, CONTAINER = ALL, CONTAINER_DATA가 CDB 전용 문법이기 때문임
c##으로 시작하는 이름은 CDB 공통 사용자 접두어라 non-CDB에서는 ORA-65094가 남
grant ... to 계정; -- 주석처럼 ; 뒤에 주석을 붙이면 SQLPlus가 그 줄을 문장 끝으로 보지 않아 다음 줄과 합쳐 버리고, 뒤의 GRANT가 실행되지 않아 V$SESSION 조회가 ORA-00942로 실패했음
실습에서는 주석을 윗줄로 옮기고 계정을 지운 뒤 다시 실행했음
SQLPlus 명령 뒤의 주석과 SQL 종결자 뒤의 주석은 독립된 줄에 둠
PostgreSQL에서 -h 127.0.0.1로 접속하면 pg_hba.conf의 비밀번호 인증 규칙을 타는데 실습 postgres 계정에는 비밀번호가 없음
실습에서는 스크립트를 sudo -u postgres psql(local peer 인증)로 실행했음
pg_monitor만으로는 EXPLAIN을 볼 수 없음
EXPLAIN은 테이블 SELECT 권한이 필요해 pg_read_all_data를 더 줌
이 롤은 모든 테이블을 읽을 수 있으므로 "조회 권한만"이라도 데이터 열람 범위는 넓음
실습 확인 스크립트들은 비교용 세션을 관리 계정으로 엶