실패한 작업이 계속 재시도되면서 큐를 먹고 있었다. 정리하려고 상태를 하나 만들었다.
ready → working → done
→ failed
→ deleted (새로 만든 것)
deleted 로 바꾸면 더 이상 안 집는다. 그런데 이름 때문에 문제가 생겼다.
Table of contents
Open Table of contents
이름이 뜻을 흐렸다
한 달쯤 뒤에 다른 사람이 정리 배치를 만들었다.
DELETE FROM reward_job WHERE status = 'deleted' AND reg_date < DATE_SUB(NOW(), INTERVAL 7 DAY);
deleted 상태니까 지워도 되겠다고 판단한 것이다.
그런데 그 상태는 지워도 되는 것이 아니라 더 이상 처리하지 않기로 한 것이었다. 왜 포기했는지가 그 행에 남아 있었는데 DELETE 하고 나니 그 정보가 없어졌다.
두 가지가 달랐다
정리해 보니 이런 차이였다. 처리 포기는 이 작업을 더 진행하지 않는다는 것이고 왜 포기했는지는 남으며 통계에도 잡힌다. 기록 삭제는 이 행 자체를 없애는 것이라 아무것도 안 남는다.
앞은 상태고 뒤는 행위다. 앞의 것은 처리를 멈추는 결정이고 뒤의 것은 자료를 버리는 결정이라 두 결정이 같은 이름을 쓰면 그 차이가 사라진다.
이름을 바꿨다
ready → working → done
→ failed (실패, 재시도 대상)
→ abandoned (포기, 재시도 안 함)
abandoned 로 바꾸니 지워도 되는 것으로 읽히지 않는다. 포기한 이유도 컬럼에 남겼다.
ALTER TABLE reward_job
ADD COLUMN abandon_reason VARCHAR(100) NULL,
ADD COLUMN abandon_date DATETIME NULL;
abandoned 대상 계정 없음 2016-03-04
abandoned 아이템 삭제됨 2016-03-04
abandoned 재시도 5회 초과 2016-03-05
GROUP BY abandon_reason 으로 이유별로 세어 보면 무엇을 손봐야 하는지 나온다. status 만 남기면 그 작업이 왜 안 됐는지를 다시 조사해야 한다.
실제로 지우는 것의 처리
행을 영원히 두면 표가 커지므로 지우는 것도 필요하다. 다만 지우기 전에 남길 것을 남겼다.
INSERT INTO reward_job_archive
SELECT * FROM reward_job
WHERE status IN ('done', 'abandoned') AND reg_date < DATE_SUB(NOW(), INTERVAL 90 DAY);
DELETE FROM reward_job
WHERE status IN ('done', 'abandoned') AND reg_date < DATE_SUB(NOW(), INTERVAL 90 DAY);
90일이 지난 것은 reward_job_archive 로 옮기고 본 표에서 지운다. 보관 표는 CREATE TABLE ... LIKE 로 뜨고 조회가 드무니 인덱스를 최소로 뒀다.
본 표는 작게 유지되고 이력은 남는다. 자주 조회하는 표에서 안 쓰는 행을 덜어 내는 것이 목적이었다.
검증 — 상태 문서와 개수 세기
상태가 다섯 개가 됐으니 각각이 무슨 뜻인지 적었다.
ready 대기. 처리기가 집을 대상
working 처리 중. 집은 처리기 정보가 worker_id 에 있음
done 완료
failed 실패. 재시도 대상 (try_count < 5)
abandoned 포기. 재시도 안 함. 이유는 abandon_reason 에 있음
각 상태에서 어느 상태로 갈 수 있는지도 적었다.
ready → working → done
→ failed → ready (재시도)
→ abandoned (5회 초과)
→ abandoned (복구 불가)
이 그림이 있으면 새 상태를 넣을 때 어디에 넣을지가 정해진다.
문서를 만들고 나서 실제 자료가 그대로인지 봤다.
SELECT status, COUNT(*) FROM reward_job GROUP BY status;
ready 12
working 847 ← 이상하다
done 4128
failed 23
abandoned 91
working 이 847개다. 처리 중인 것이 그렇게 많을 리 없다.
집어 놓고 죽은 것들이 회수 안 된 채 쌓여 있었고 회수 배치가 멈춰 있었다. 상태별 개수를 세어 보니 멈춘 것이 드러난 것이고 문서를 만드는 과정에서 나왔다. 정의에 없는 값이 들어 있는 행도 이 집계에 한 줄로 나타난다.
정리
- 더 이상 처리하지 않는 것과
DELETE는 다른 일이다 - 앞은 상태고 뒤는 행위다
- 이름이 뜻을 흐리면 다른 사람이 다르게 해석한다
deleted대신abandoned로 두고 실제 삭제와 구분한다abandon_reason컬럼에 이유를 남긴다GROUP BY abandon_reason으로 세면 무엇을 손볼지 나온다- 지울 때는 보관 표로 옮기고 본 표를 작게 유지한다
- 보관 표는 조회가 드무니 인덱스를 최소로 둔다
status값마다 뜻과 갈 수 있는 경로를 적는다- 그 그림이 있으면 새 상태를 넣을 자리가 정해진다
GROUP BY status로 세면working에 멈춘 것이 드러난다