여러 채널에 순차로 복구를 돌리는 중이었고 첫 채널이 끝나 다음을 골라야 했다. 기준은 작은 것부터였고 작으면 실패해도 영향이 적기 때문이다.
Table of contents
Open Table of contents
제외 조건 없이 센 규모
채널별 규모를 세는 쿼리로 작은 순서를 뽑았다. 175건과 183건과 193건짜리 채널이 나왔고 이 정도면 시작하기 좋아 보였다.
그런데 이 작업에는 건드리면 안 되는 제외 대상 공급사 목록이 따로 있었다. 처음 센 쿼리에는 그 조건이 안 들어가 있었다.
소형으로 보이던 것의 실체
제외 조건을 넣고 다시 세니 그 세 채널이 각각 0건과 1건과 0건이 됐다. 소형으로 보이던 채널들이 전부 제외 대상 고객의 독점 채널이었던 것이다.
제외를 적용하면 처리할 것이 없다. 작은 채널이 아니라 우리가 건드릴 것이 없는 채널이었고 두 문장은 완전히 다른 뜻이다. 조건 하나를 빼먹었을 뿐인데 후보 목록의 앞자리가 통째로 바뀌었다.
연속이 아닌 규모
제외를 적용한 뒤 순서를 다시 보니 규모가 연속이 아니었다. 직전에 끝낸 채널이 1,213건이고 다음 후보 둘이 2천 건대인데 그다음이 3만 5천 건대로 뛴다.
조금씩 늘려 가는 방식이 안 된다는 뜻이다. 다음 단계가 열일곱 배이므로 2천 건대를 끝낸 뒤 바로 3만 건대에 들어가게 된다. 미리 알고 있으면 그 앞에서 준비를 할 수 있고 모르면 규모에 맞는 준비 없이 들어간다.
두 지표를 함께 보는 기준
2천 건대 후보 둘의 성격도 달랐다. 하나는 등록 건수가 0이었고 다른 하나는 사내 독립 배포 서비스로 전송하는 특수 채널이었다.
등록이 0이면 갱신 작업이 구조적으로 발생할 수 없고 외부로 나가는 전송도 없다. 복구 로직은 똑같이 도는데 무엇이 잘못돼도 우리 DB 안에서 끝난다. 실패해도 밖에 티가 안 나는 대상이 검증에는 가장 좋은 대상이었다.
여기서 규칙이 하나 나왔다. 확대 순서는 제외 조건을 적용한 개수와 등록 수를 함께 보고 정한다. 개수만 보면 위험한 것을 고를 수 있고 등록 수만 보면 규모를 모른다.
병렬 실행 전의 준비
실행을 준비하다가 하나 더 걸렸다. 여러 채널을 병렬로 돌리면 같은 진행 기록 파일에 동시 쓰기가 발생하는데 파일 기반 DB라 그것에 약하다.
sqlite3.connect(path, timeout=60.0)
conn.execute('PRAGMA busy_timeout=60000')
연결 수준과 DB 수준 둘 다에 대기 시간을 넣어야 한다. 이걸 실행 전에 넣은 것이 중요했다. 돌리다가 잠금 오류를 만나면 그 실행분이 날아가고 어디까지 갔는지도 기록에 안 남는다.
정리
- 규모를 셀 때 제외 조건을 적용하고 센다
- 안 넣으면 실제 작업 대상과 크게 어긋난다
- 소형으로 보이던 것이 전부 제외 대상 독점일 수 있다
- 작은 채널과 건드릴 것이 없는 채널은 다른 뜻이다
- 규모가 연속이 아니라 뛰면 조금씩 늘리는 방식이 안 된다
- 확대 순서는 개수와 외부 노출 위험을 함께 보고 정한다
- 등록이 0인 대상은 실패해도 밖에 안 나가서 검증에 좋다
- 병렬 실행 전에 파일 DB의 잠금 대기 설정을 넣는다