1. 장애 개요
운영 중 아래 오류 발생:
ORA-00600: internal error code, arguments: [qosdExpStatRead: expcnt mismatch]
- DBMS_SCHEDULER 사용자 Job 수행 중 발생
- Job 내부에서 DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO 호출
- 이후 DBMS_STATS 관련 기능 전반 실패
- 사용자 Job 외에도 15분 마다 발생(백그라운드 통계관련 프로세스로 추정)
2. 원인 분석
해당 오류의 핵심 원인은 옵티마이저 통계 메타데이터 불일치 .
구체적으로는 아래 두 내부 테이블 간 데이터 불일치:
- SYS.EXP_OBJ$
- SYS.EXP_STAT$
3. 진단 쿼리
문제 데이터는 다음 쿼리로 확인 가능하다.
WITH b AS (
SELECT COUNT(*) cnt, objn, snapshot_id
FROM sys.exp_stat$
GROUP BY objn, snapshot_id
)
SELECT *
FROM sys.exp_obj$ a, b
WHERE a.objn = b.objn
AND a.snapshot_id = b.snapshot_id
AND a.exp_cnt <> b.cnt;
4. 조치 방법
통계 재수집 혹은 만으로 통계import로 조치하려 했으나 dbms_stat 패키지 사용이 불가하였음
① 불일치 데이터 삭제
DELETE FROM sys.exp_stat$
WHERE snapshot_id = [snap_id]
AND objn = [obj_num];
② 메타데이터 정합성 맞춤
UPDATE sys.exp_obj$
SET exp_cnt = 0
WHERE snapshot_id = [snap_id]
AND objn = [obj_num];
③ 대상 테이블 통계 삭제
EXEC DBMS_STATS.DELETE_TABLE_STATS([schema],[table], FORCE=>TRUE);
④ 통계 재수집
EXEC DBMS_STATS.GATHER_TABLE_STATS(
OWNNAME=>[schema],
TABNAME=>[table],
DEGREE=> [parallel degree],
ESTIMATE_PERCENT=>[],
FORCE=> TRUE,
CASCADE=> TRUE
);
5. 결과
- ORA-600 오류 해결
- DBMS_STATS 정상 동작 복구
- Scheduler Job 정상 수행
6. 오류 재현 테스트 (신규 테이블 기반)
최신 버전(Oracle 19c)에서도 특정 조건 하에 해당 오류가 재현됨을 확인하였다.
[단계 1: 테스트 환경 구축]
CREATE TABLE [schema].[table] (
ID NUMBER,
VAL1 NUMBER,
VAL2 NUMBER,
TEXT_DATA VARCHAR2(100)
);
INSERT INTO [schema].[table]
SELECT LEVEL, MOD(LEVEL, 100), MOD(LEVEL, 50), RPAD('A', 50, 'B')
FROM DUAL CONNECT BY LEVEL <= 10000;
COMMIT;
-- OBJECT_ID 확인 (예: 349764)
SELECT OBJECT_ID FROM DBA_OBJECTS
WHERE OWNER = [schema] AND OBJECT_NAME = [table];
-- 349764
[단계 2: Expression Statistics 생성 유도] 옵티마이저가 계산식을 학습하도록 쿼리를 반복 수행한 후 메모리 정보를 디스크로 밀어넣는다.
-- 식(Expression) 사용 쿼리 반복 실행 (내부 딕셔너리에 등록될 기회를 줌)
-- 옵티마이저에게 'VAL1 + VAL2'라는 식을 학습시킴
SELECT /*+ MONITOR */ COUNT(*)
FROM [schema].[table] WHERE (VAL1 + VAL2) > 50;
SELECT *
FROM DBA_EXPRESSION_STATISTICS
WHERE TABLE_NAME = '[table]';
-- [schema] [table] 18316653909056587559 LATEST 21900 0.0000011103939567795 "VAL1"+"VAL2" 2026/03/24 10:47:49 2026/03/24 10:48:58
-- 메타데이터 생성 확인, 아직 생성 안됨
SELECT * FROM sys.exp_stat$ WHERE OBJN = 349764;
SELECT * FROM sys.exp_obj$ WHERE OBJN = 349764;
-- NO ROWS
-- 메모리에 있는 통계 정보를 딕셔너리 테이블(SYS.EXP_STAT$ 등)로 강제 저장
EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
-- 메타데이터 생성 확인
SELECT * FROM sys.exp_stat$ WHERE OBJN = 349764;
--15958839778340835652 349764 21900 1 2026/03/24 10:52:02 2026/03/24 10:52:02
SELECT * FROM sys.exp_obj$ WHERE OBJN = 349764;
--349764 1 1
[단계 3: 데이터 조작을 통한 Crash 유도]
-- 실제 통계 데이터는 1개이나, 관리 대장(EXP_OBJ$)의 카운트를 강제로 조작
UPDATE SYS.EXP_OBJ$
SET EXP_CNT = EXP_CNT + 5
WHERE OBJN = 349764;
COMMIT;
-- 딕셔너리 캐시 정화 (SGA에 예전 값이 남지 않도록)
ALTER SYSTEM FLUSH SHARED_POOL;
[단계 4: 결과 확인]
-- 통계 정보를 참조하는 쿼리 실행 시 즉각 발생
SELECT /*+ DYNAMIC_SAMPLING(4) */ COUNT(*)
FROM [schema].[table] WHERE (VAL1 + VAL2) > 50;
EXEC DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
-- 결과: ORA-00600 [qosdExpStatRead: expcnt mismatch] 발생 확인
결론
- Oracle 19c 환경에서도 Expression Statistics Usage(ESU) 기능이 활성화되어 있다면 본 장애는 언제든 발생 가능하다.
- 특히 대량의 DML이나 빈번한 통계 Flush 작업 중 예기치 못한 인터럽트가 발생할 경우 메타데이터 불일치가 생길 수 있다.
- 조치 시 SYS 테이블을 직접 수정해야 하므로, 반드시 사전 진단 쿼리를 통해 정확한 OBJN과 SNAPSHOT_ID를 특정해야 한다.
'Trouble Shooting' 카테고리의 다른 글
| ORA-03150: 데이터베이스 링크를 위한 통신 채널의 파일 끝, ORA-02063: line가 선행됨 (0) | 2026.03.26 |
|---|---|
| ORA-01652: unable to extend temp segment by 128 in tablespace TEMP (0) | 2025.06.10 |
| ORA-3136 / WARNING: inbound connection timed out (0) | 2025.05.23 |