중지시킨 것이 다시 살아나 있다는 보고가 왔고 한두 건이 아니라 열일곱 건이었다. 어디선가 되살리고 있다는 뜻인데 그 자리가 한 곳이라는 보장이 없었다.
Table of contents
Open Table of contents
증상 — 다시 살아난 열일곱 건
한 곳을 찾아서 막는 방식으로 가면 나머지 경로가 남아 있을 때 같은 일이 다시 난다. 그래서 막기 전에 경로가 몇 개인지를 먼저 확정하기로 했다.
열일곱 건 각각이 어떤 처리로 살아났는지가 distribution_product_jobs 에 남아 있었다.
SELECT dp_id, job, event, created_at
FROM distribution_product_jobs
WHERE dp_id IN (...)
ORDER BY dp_id, created_at;
stop 다음에 update 가 들어와 살아나는 패턴이 보였고 그 이력을 어느 컬럼으로 GROUP BY 하느냐가 경로 수를 세는 방법이 된다.
이벤트 컬럼으로 본 경로
event 컬럼으로 GROUP BY 해 COUNT(*) 를 내 보니 세 종류였다.
ProductStatusChangedEvent 관리자가 상태를 직접 바꿈
(마스터 수정 후 연동) 상위 수정 시 전 채널에 자동 갱신
NULL 정기 배치 동기화
세 종류는 서로 다른 화면과 다른 배치에서 오는 것이었고 코드도 각각 달랐다. event 한 컬럼으로 GROUP BY 하는 것만으로 세 경로가 한눈에 드러난 셈이었다.
하나를 막아도 둘이 남는다
건수가 가장 많은 경로만 막으면 그 순간에는 줄어든 것처럼 보인다. 그러나 나머지 둘이 남아 있으므로 며칠 뒤에 다시 같은 보고가 온다.
이런 상황에서 부분적으로 막는 것은 문제를 없애는 것이 아니라 발생 속도를 늦추는 것이다. 늦어진 만큼 원인이 해결된 것으로 오해되기 쉬워서 오히려 나쁠 수도 있었다.
상위 상태라는 공통 지점
grep 으로 세 경로의 코드를 나란히 놓고 보니 셋 다 상위 행의 상태를 보고 진행 여부를 정하고 있었다. 그 상태가 살아 있으면 하위를 되살리는 것이 각 경로의 공통 동작이었다.
그러면 막을 자리는 세 곳이 아니라 그 상위 상태 하나가 된다. 영구 중지를 할 때 하위만 UPDATE 하지 않고 상위까지 함께 내리도록 바꿨다.
실재하는 불일치와 점검 쿼리
바꾸면서 상위와 하위를 JOIN 해 이미 어긋나 있는 건을 COUNT(*) 로 세어 봤는데 실제로 상당수가 있었다. 이 불일치는 이론적인 가능성이 아니라 지금 자료에 들어 있는 상태였다.
계속 생길 수 있는 것이므로 어긋난 건을 뽑는 점검 SELECT 를 만들어 cron 으로 주기적으로 돌리게 했다. 경로를 다 세고 나서 막았기 때문에 이 점검이 무엇을 잡는지도 분명했다.
정리
- 중지된 것이 되살아나는 경로가 셋이었다
- 하나를 막아도 나머지로 살아난다
- 부분적으로 막으면 발생 속도만 늦춘다
- 이력의 이벤트 컬럼으로
GROUP BY하면 경로가 한눈에 나온다 - 여러 경로가 상위 상태를 보고 있으면 거기가 공통 지점이다
- 영구 중지는 상위까지 함께 바꾼다
- 상위와 하위의 상태 불일치가 실재한다
- 경로를 다 세고 나서 막는다