모든 장애를 분석할 때 가장 기본이 되는 것은 장애시점 대비 가장 최근에 변경이 가해진 것부터 확인을 해야 한다는 점이다. 이유는 해당 변경 작업 시 예상치 못했 던 영향으로 장애가 발생할 가능성이 매우 높기 때문이며, 경험상 이는 굉장히 현 명한 접근방법이다.
게다가 데이터베이스 전환은 단순한 설정 작업과는 달리 모든 업무에 영향을 줄 수 있으므로 티베로 전환을 완료하고 당분간은 어떠한 문제가 발생했을 때 관련된 모 든 담당자가 티베로의 문제는 아닌지 먼저 의심하게 됨은 데이터베이스 관리자나 티베로 엔지니어가 감수해야할 몫일 것이다.
데이터베이스 관리자가 해야 할 일은 그러한 리포트를 받았을 때 친절하고 전문적으로 티베로 문제가 아님을 증명함으 로써 관련된 담당자들에게 데이터베이스의 신뢰도를 스스로 깨닫게 해주는 것이라 고 생각한다. 다음에 소개하는 두 가지 에피소드는 담당자가 데이터베이스 문제라 고 강하게 확신하였지만 티베로는 아무런 문제가 없음을 증명한 사건이다.
티베로 오픈 후 데이터에 문제가 생겼다는 연락을 받았다. 소속 회사가 진행한 프 로젝트 방법론은 SQL의 성능과 실패에 대한 호환성을 외산 DBMS 수준으로 만드 는 것이 목표였고 정확한 데이터가 구축되고, 추출되는 부분은 많은 검증을 하지 않고 당연히 될 것이라 생각하며 티베로 엔진을 신뢰하였다.
그러기에 사전에 대비 하지 못한 부분인 ‘데이터에 문제가 생겼다는 연락’은 가장 두려운 일 중에 하나였 기에 상당히 긴장했었으나, 다행히도 담당자가 RANK 함수와 ROW_NUMBER 함수의 정확한 사용법을 착각해서 발생한 에피소드에 불과했다. 어떤 문제였는지 먼 저 정의를 살펴보자.
위 정의만 보아도 어떠한 문제인지 예상했을 것이다. ROW_NUBMER 함수는 PARTITION BY로 구분된 그룹 안에 중복이 있더라도 유일한 번호를 부여하는 것 에 비해 RANK의 경우 순위를 부여하기 때문에 동일 값은 동일한 순위를 부여하는 것이 정상이다.
따라서 유일한 값을 기대하며 RANK 함수를 사용한 것이 잘못된 점이고 티베로에는 아무런 문제가 없음을 확인, 필요 시 ROW_NUMBER 함수를 사용할 것을 친절히 안내하였다.
SELECT A,B, RANK() OVER(PARTITION BY A ORDER BY A,B) AS RANK_COL FROM ( SELECT '1' A, '100' B FROM DUAL UNION ALL SELECT '1' A, '100' B FROM DUAL UNION ALL SELECT '1' A, '150' B FROM DUAL UNION ALL SELECT '1' A, '200' B FROM DUAL UNION ALL SELECT '2' A, '100' B FROM DUAL UNION ALL SELECT '2' A, '150' B FROM DUAL UNION ALL SELECT '2' A, '200' B FROM DUAL ); A B RANK_COL - ---- ------------ 1 100 1 1 100 1 <-- 중복 발생 1 150 3 1 200 4 2 100 1 2 150 2 2 200 3 SELECT A,B, ROW_NUMBER() OVER(PARTITION BY A ORDER BY A,B) AS RANK_COL FROM ( SELECT '1' A, '100' B FROM DUAL UNION ALL SELECT '1' A, '100' B FROM DUAL UNION ALL SELECT '1' A, '150' B FROM DUAL UNION ALL SELECT '1' A, '200' B FROM DUAL UNION ALL SELECT '2' A, '100' B FROM DUAL UNION ALL SELECT '2' A, '150' B FROM DUAL UNION ALL SELECT '2' A, '200' B FROM DUAL ); A B RANK_COL - --- --------- 1 100 1 1 100 2 1 150 3 1 200 4 2 100 1 2 150 2 2 200 3
/*+ INDEX_DESC(MAXTEST MAXTEST_IDX01) */와 같이 옵티마이저에 어떠 한 인덱스를 사용할지 직접 지시하는 힌트를 사용하는 SQL을 종종 확인할 수 있 다.
그런데 이때 힌트에 쓰여진 테이블 혹은 인덱스 이름에 오타가 발생하여 실제 오브젝트 이름과 상이하게 되면 위 힌트는 당연히 사용되지 않을 것이다.
사실 오 타가 발생한 것은 SQL 문장과 힌트를 비교하면 되므로 쉽게 발견할 수 있는 문제 인데 소속 회사에서 발생한 오타는 쉽게 발견하지 못해 한참 동안을 티베로가 힌트 를 제대로 사용하지 못해 발생하는 문제로 착각했던 사례가 있어 소개한다. 다음의 내용을 살펴보자.
인덱스 명명규칙을 고려했을 때 힌트는 전혀 문제가 없는 것으로 보인다(실제로 문 제가 없다고 생각했었다). MAXTEST라는 테이블 이름도 오타가 없고 MAXTEST_ IDX01의 이름도 정확하다. 뭐가 문제였을까?
문제는 MAXTEST가 실제 테이블명 과 다른 동의어(SYNONYM)라는 것이었다. 소속 회사는 테이블 이름과 다른 동의 어를 사용하는 경우가 거의 없으므로 MAXTEST가 동의어라고는 생각지도 못하였 다.
실제로 MAXREAL이 테이블 이름이고 인덱스도 그에 해당하는 MAXREAL_ IDX01이었다. 따라서 오타 없는 제대로 된 힌트는 아래와 같다.
/*+ INDEX_DESC(MAXTEST MAXREAL_IDX01) */ PROCESS_DT FROM TIBEROTEST.MAXTEST WHERE ROWNUM < 2;
위 문제는 힌트를 올바르게 적용해서 처리하였다. 그리고 티베로 프로젝트가 종료 된 지금 시점에서 생각해보니 프로젝트 진행 중에도 발견된 이슈가 실제 티베로 문 제인지 사용방법의 문제인지를 밝히는 데 꽤 많은 시간이 투여되었고, 때로는 무조 건 데이터베이스 문제로 생각하는 관련 담당자의 태도에 서운하기도 했었던 것 같 다.
그러나 서두에서 밝힌 것처럼 이러한 과정 역시 전환 작업 과정 중에 하나이며 넘어야 할 산이고 감당해야할 몫이라고 생각한다.
- 강좌 URL : http://www.gurubee.net/lecture/4147
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.