Quiz: Resumable Bulk Sync
한국어 원문으로 표시합니다.
ORDER BY updated_at 에 LIMIT/OFFSET 으로 전체를 순회하는 동안, 이미 지나온 페이지의 행이 갱신됐다. 무슨 일이 생기는가?
- 갱신된 행이 정렬 맨 뒤로 가면서 뒤의 행들이 앞으로 당겨져, 그만큼이 읽히지 않고 지나간다
- 오프셋이 가리키는 행이 바뀌었으므로 데이터베이스가 오류를 내고 순회가 중단된다
- 갱신된 행은 이미 읽었으므로 아무 영향이 없고 나머지 순회는 정확하다
- 정렬 순서가 바뀌므로 같은 행이 계속 다시 읽혀 순회가 끝나지 않는다
커서를 WHERE updated_at > :last 하나로만 잡았다. 같은 updated_at 을 가진 행이 다섯 개 있고 페이지 크기가 3 이면?
- 다섯 행이 모두 한 페이지에 들어오도록 페이지 크기가 자동으로 늘어난다
- 첫 3개를 읽은 뒤 커서가 그 시각으로 올라가, 같은 시각의 나머지 2개가 통째로 사라진다
- 다섯 행을 모두 읽은 뒤 같은 자리를 무한히 반복해서 읽는다
- 정렬이 불안정해져 다섯 행의 순서가 실행마다 달라질 뿐 누락은 없다
커서 방식으로 바꾼 뒤에도 같은 행이 두 번 들어온다. 어떻게 보아야 하는가?
- 커서 계산에 버그가 있다. 중복이 하나라도 나오면 구현이 틀린 것이다
- 원본의 정렬이 불안정한 것이므로 원본 쪽에 정렬 키 추가를 요청해야 한다
- 우리가 지나온 뒤 그 행이 갱신되어 커서 뒤로 온 것이다. 사실 그대로이므로 받는 쪽을 멱등하게 만든다
- 워터마크를 처리 전에 저장하고 있다는 신호다. 저장 시점을 뒤로 옮기면 사라진다
워터마크를 언제 저장해야 하는가?
- 요청을 보내기 직전에. 그래야 중단돼도 같은 페이지를 다시 요청하지 않는다
- 받은 행을 처리한 뒤에. 중단되면 그 페이지를 다시 받게 되지만, 잃는 것보다는 낫다
- 전체 순회가 끝난 뒤 한 번만. 중간 저장은 부분 상태를 남겨 위험하다
- 받은 직후 처리하기 전에. 처리 실패는 다음 실행에서 어차피 다시 잡힌다
원본이 어떤 필드를 고쳐도 updated_at 을 갱신하지 않는 경우가 있다. 커서 방식에서 이것이 왜 치명적인가?
- 커서 비교가 실패해 순회가 오류로 끝난다
- 그 변경은 커서보다 뒤로 오지 않으므로 우리가 영영 보지 못한다
- 같은 시각의 행이 늘어나 페이지 경계 문제가 더 자주 생긴다
- 워터마크가 뒤로 가서 이미 받은 행을 계속 다시 받는다
대조에서 원본과 사본의 건수가 정확히 같았다. 무엇을 더 확인해야 하는가?
- 아무것도. 건수가 같으면 같은 집합이므로 동기화는 성공한 것이다
- 순서. 두 쪽의 정렬이 같아야 같은 데이터로 볼 수 있다
- 받은 시각. 두 쪽의 수집 시각이 같아야 비교가 성립한다
- id 집합과 값. 한 건이 빠지고 한 건이 중복되면 건수는 그대로다