SMF2 포럼에서 20년 이상의 활동 데이터를 가져와 로컬 컨테이너에서 작업하던 중 Topic.reset_all_highest에 치명적인 버그를 발견했습니다.
데이터 가져오기 후 데이터베이스에는 약 60,000개의 일반 토픽과 약 400,000개의 private_message 토픽이 표시되며, Topic.reset_all_highest의 쿼리가 행의 기하급수적 증가를 유발하여 디스크 공간이 부족해졌습니다(초기 여유 공간 120GB 기준).
현재는 쿼리를 관리 가능한 크기로 나누어 Postgres에서 직접 실행해 보고 있지만, 이는 당연히 비최적이며(그리고 실제로 동작하여 올바른 결과를 도출하는지조차 확실하지 않습니다).
다른 사람들도 비슷한 문제를 겪었는지 확인해 보았지만 아무것도 찾을 수 없어, 이것이 제 환경 설정과 관련이 있는 것은 아닌지 궁금합니다. 참고로 최신 docker 버전을 사용하고 있습니다.
최근에 중간 규모의 임포트를 진행했는데, Topic.reset_all_highest에서 무한정 멈춰 있는 것 같습니다. 계속 진행하기 위해 Postgres에서 쿼리를 강제로 종료해야 했습니다. 이전에는 이런 문제가 없었으며, Postgres 서버가 과부하 상태(여러 사이트가 연결되어 있음) 때문일 수도 있다고 생각했습니다.
다음 단계는 다른 Postgres 서버로 이전하는 것이었지만, 아직 시간이 나지 않았습니다.
“쿼리 분할” 실험의 첫 두 단계(X와 Y, 공개 주제용)가 순조롭게 진행되었기 때문에 Z에 대해서도 시도해 보았습니다. 그런데 프로그램이 멈췄습니다. 즉, postgres 활동에서 쿼리가 활성 상태였고, top에서 프로세스가 100%로 실행 중인 것으로 나타났습니다.
그래서 SQL을 다시 살펴보니 문제를 발견했습니다. 두 쿼리 모두 다음과 같이 끝납니다.
WHERE
topics.archetype <> 'private_message' AND
X.topic_id = topics.id AND
Y.topic_id = topics.id AND
(
topics.highest_staff_post_number <> X.highest_post_number OR
topics.highest_post_number <> Y.highest_post_number OR
topics.last_posted_at <> Y.last_posted_at OR
topics.posts_count <> Y.posts_count OR
topics.word_count <> Z.word_count
)
(다른 쿼리는 물론 'private_message’를 아키타입으로 사용합니다)
이는 쿼리에
Z.topic_id = topics.id가 빠져 있다는 뜻이며, 이로 인해 전체적인 기하급수적 증가가 발생했습니다.
쿼리의 WHERE 절을 다음과 같이 변경했습니다.
WHERE
topics.archetype <> 'private_message' AND
X.topic_id = topics.id AND
Y.topic_id = topics.id AND
Z.topic_id = topics.id AND
(
topics.highest_staff_post_number <> X.highest_post_number OR
topics.highest_post_number <> Y.highest_post_number OR
topics.last_posted_at <> Y.last_posted_at OR
topics.posts_count <> Y.posts_count OR
topics.word_count <> Z.word_count
)
이로 인해 제 문제는 해결되었습니다.
PR을 열어야 할까요?
그렇게 생각됩니다. 해당 문제를 일으킨 커밋을 찾을 수 있다면 더 설득력이 있을 것입니다.
이 문제를 위해 PR을 열었습니다. 다만 몇 가지 불운한 제한 사항이 있습니다(예: 이 변경 사항을 어떻게 테스트해야 할지 상상할 수 없습니다).
이 변경 사항은 올바르게 보이며, 병합합니다.
(테스트 측면에서는 커버리지가 있어야 하며, 이를 검증하기 위한 간단한 테스트 하나면 충분합니다. 다만 회귀가 없는지 확인해야 합니다)