느린 쓰기(INSERT/UPDATE 지연)
INSERT/UPDATE/DELETE 작업이 예상보다 느리다. 먼저 쓰기가 무엇을 기다리는지(commit/redo, 락, 디스크, 행 단위 오버헤드) 파악한 뒤 단계적으로 근본 원인을 좁혀 간다.
쓰기는 무엇을 기다리는가?
대기 이벤트를 보고 병목을 분류한다: commit/redo(WAL) 동기화, 락, 디스크 쓰기 지연, 행 단위 인덱스/트리거 오버헤드 중 무엇이 지배적인가?
SELECT event, total_waits, ROUND(time_waited/100,1) AS sec_waited
FROM v$system_event
WHERE event IN ('log file sync','log file parallel write','enq: TX - row lock contention','db file sequential read')
ORDER BY time_waited DESC;- commit / redo 대기(WAL sync)
- 락 대기
- 행 단위 오버헤드 의심(인덱스/트리거)
- 디스크 쓰기 지연이 큼
커밋 패턴인가, fsync인가?
행마다 별도 커밋(autocommit)을 하면 행 수만큼 redo/로그 동기화가 발생한다. 반대로 커밋 수는 적절한데 각 커밋이 fsync를 기다린다면 문제는 로그 디스크 지연이다.
SELECT name, value FROM v$sysstat WHERE name IN ('user commits','redo writes','redo size');
SELECT ROUND(time_waited_micro/GREATEST(total_waits,1)/1000,2) AS ms_per_sync FROM v$system_event WHERE event='log file sync';- Autocommit / 행마다 커밋
- 커밋이 로그 동기화(fsync)를 기다림
누가 락을 보유하고 있는가?
쓰기가 락을 기다린다면: 다른 세션이 같은 행/인덱스를 보유하고 있거나, 다수의 세션이 같은 '핫' 행에 쓰려 하고 있을 수 있다.
SELECT s.sid, s.serial#, s.username, s.blocking_session, s.event, s.seconds_in_wait
FROM v$session s WHERE s.blocking_session IS NOT NULL;- 다른 세션이 락을 보유 중
- 다수의 세션이 같은 핫 행에 씀
행 단위 오버헤드는 어디서 오는가?
모든 INSERT/UPDATE는 테이블의 모든 인덱스도 갱신하고 트리거/제약 조건을 실행한다. 인덱스가 과도하거나 트리거가 무거우면 쓰기가 크게 느려진다.
SELECT index_name, uniqueness FROM user_indexes WHERE table_name='T';
SELECT trigger_name, triggering_event FROM user_triggers WHERE table_name='T';- 테이블에 인덱스가 너무 많음 / 불필요한 인덱스
- 무거운 트리거 또는 제약 조건 비용
근본 원인: autocommit / 행마다 커밋
행마다 별도 커밋을 하면 행 수만큼 redo/로그 동기화가 반복된다. 작업을 묶으면 커밋 수(따라서 fsync 수)를 크게 줄일 수 있다.
근본 원인: 느린 redo/로그 디스크(fsync 지연)
모든 커밋은 redo/WAL 레코드가 내구성 있는 스토리지에 기록될 때까지(fsync) 기다린다. 로그 디스크가 느리면(높은 쓰기 지연, 부족한 IOPS) 모든 커밋이 그 지연을 떠안는다.
근본 원인: 다른 세션이 락을 보유 중
쓰기가 다른 세션이 보유한 행/인덱스 락을 기다리고 있다. 블로커는 대개 오래 실행 중인 트랜잭션이거나 커밋을 잊은 트랜잭션이다.
근본 원인: 핫 행 경합
다수의 세션이 같은 행(예: 카운터, 시퀀스 번호, 잔액)에 쓰려 한다. 모두 같은 락을 기다리며 쓰기가 직렬화된다.
근본 원인: 과도한 인덱스 오버헤드
테이블의 모든 인덱스는 쓰기마다 갱신된다. 인덱스가 많거나 사용되지 않는 인덱스가 있으면 INSERT/UPDATE가 직접 느려진다.
근본 원인: 무거운 트리거 / 제약 조건
쓰기마다 실행되는 트리거나 검증 중인 제약 조건(특히 인덱스 없는 외래 키 검사)은 모든 행에 추가 비용을 더한다.