'bundle exec rake db:migrate'가 캘린더 마이그레이션으로 인해 오래 걸림

안녕하세요, 여러분! 도움을 요청드립니다!

혹시 이 문제를 경험해 보신 분 계신가요?

./launcher rebuild app 명령어를 실행했는데, 이 지점까지 진행되더니 그 뒤로 멈춰 버립니다.

지금 뭔가 동작은 하고 있지만, 속도가 매우 느립니다. 저는 지난 3년간 Digital Ocean 드롭렛을 직접 설치해 포럼을 운영해 왔는데, 이런 현상은 처음이라 상당한 다운타임이 발생하고 있습니다. 이 문제를 해결할 방법이 있을까요? 포럼의 이미지와 관련이 있는 것일까요?

다른 SSH 세션을 열고 어떤 마이그레이션이 문제를 일으키는지 찾아볼 수 있을까요?

ps aux | grep postgres와 같은 명령어로 시작 부분을 확인할 수 있을 것입니다.

저는 리눅스 전문가(솔직히 말하면 아마추어도 아니고)는 아니지만, 한번 시도해 보겠습니다.

메모리 부족일 것 같습니다. 다음을 시도해 볼 수 있습니다.

free -h

아마도 다음도 도움이 될 수 있습니다.

du -hs /var/discourse/shared/standalone/*

메모리(RAM) 또는 디스크 공간?

두 가지 모두 넉넉해야 할 것 같습니다. 드롭렛 사양은 다음과 같습니다: 8GB 메모리 / 4 Intel vCPU / 160GB 디스크 + 200GB / Ubuntu 18.04.3 (LTS) x64

현재 db:migrate가 실행 중인 상태에서 다른 SSH 세션을 열어 해당 작업을 수행하는 것이 "안전"할까요?

나라면, 먼저 아직 활성 지원을 받는 운영체제를 갖춘 새로운 VPS를 구하는 것부터 시작하겠습니다.

네.

좋아요 - 제가 리눅스 전문가가 아니라는 점을 이해해 주세요. 당신의 게시글은 현재 우분투 빌드가 매우 오래되었다는 등의 의미를 암시하는 것 같나요?

네, 이 운영체제는 2018년 4월에 출시되어 5년간 지원되었으므로, 지원 종료 시점은 6개월 전을 넘었습니다.

정보 주셔서 감사합니다.

솔직히 말하지만, 저는 최선을 다하고 있는 아마추어입니다. 다음으로 무엇을 해야 할지 추천해 주실 수 있나요?

db:migrate 실행에 실패했는데, 메시지는 다음과 같았습니다:

client_loop: send disconnect: Connection reset

다시 로그인했을 때, 말씀하신 대로:

New release ‘20.04.6 LTS’ available.
Run ‘do-release-upgrade’ to upgrade to it.

현재 제 포럼이 다운된 상태인데, 업그레이드를 먼저 진행하고 나중에 포럼 문제를 해결하는 것이 안전할까요, 아니면 먼저 포럼을 다시 가동하는 것이 좋을까요?

:thinking: SSH 오류네요…

업그레이드 전에 백업을 해두셨나요? 그렇다면 Ubuntu 22가 설치된 새 서버를 구하고 Discourse를 설치한 뒤 백업을 복원하는 것이 가장 쉬울 것입니다.

아, 제 관리자 중 한 명이 사이트의 업그레이드 버튼을 눌렀는데, 업그레이드가 실패한 뒤 모든 것이 망가진 것 같습니다. :smiley:

마지막 백업은 어제에 이루어졌으니, 아직까지는 괜찮습니다.

기존 서버를 업그레이드하면 기존 설치 내용이 초기화되는 건가요?

(@RGJ, 인내심을 가져주셔서 감사합니다)

확실히 말하긴 어렵지만, 문제가 발생하고 있으므로 모험을 걸지는 않겠습니다. 적어도 백업이 안전한 위치에 저장되어 있는지 확인하기 전까지는요.

새 VM을 생성하고 컨테이너를 중지한 후(어차피 실행 중이 아닌 것 같으니), rsync로 모든 것을 새 서버로 복사해서 다시 시도해 볼 수 있습니다. 이 방법으로 데이터를 잃지 않고 빠르게 복구할 수 있을 가능성이 높습니다.

전부 너무 간단해 보이지만, 솔직히 말하면 나는 지금 완전 벼랑 끝인 것 같아요. 현재는 Digital Ocean 드롭렛에서 실행 중이거든요. 그래서 새 VM을 띄운다는 건데, 이 말은 좀 함의가 많은 표현인가요? 같은 드롭렛에서? 아니면 새 드롭렛에서? :woozy_face:

VM은 DigitalOcean이 드롭렛(droplet)이라고 부르는 것에 대한 일반적인 용어입니다.

관리형 호스팅을 고려해 보시는 것이 좋을 수도 있으니 제 프로필을 한번 살펴보세요 :wink:

ystemd+  7660  0.0  0.3 352060 28284 ?        S    22:31   0:00 /usr/lib/postgresql/13/bin/postmaster -D /etc/postgresql/13/main
systemd+  7667  0.0  0.1 352588  9628 ?        Ss   22:31   0:00 postgres: 13/main: checkpointer 
systemd+  7668  0.3  0.9 352060 78796 ?        Ss   22:31   0:03 postgres: 13/main: background writer 
systemd+  7669  0.0  0.1 352060 13696 ?        Ss   22:31   0:00 postgres: 13/main: walwriter 
systemd+  7670  0.0  0.1 352728 11892 ?        Ss   22:31   0:00 postgres: 13/main: autovacuum launcher 
systemd+  7671  0.0  0.0  67996  5320 ?        Ss   22:31   0:00 postgres: 13/main: stats collector 
systemd+  7672  0.0  0.0 352612  6640 ?        Ss   22:31   0:00 postgres: 13/main: logical replication launcher 
systemd+ 10900 82.0  3.8 487164 317728 ?       Rs   22:33  10:42 postgres: 13/main: discourse discourse [local] DELETE
systemd+ 10901  0.0  0.1 353432 13804 ?        Ss   22:33   0:00 postgres: 13/main: discourse discourse [local] idle

htop에서 discourse [local] delete가 CPU 100%를 차지하고 있는 것으로 보입니다. 드롭렛에는 8GB의 RAM이 있으며, 현재 사용 중인 RAM은 1GB 미만입니다(버퍼 제외).

OS가 최신 버전이 아니지만, 제 생각에는 매우 이상한 상황입니다. RAM과 디스크 공간이 충분하고, 해당 postgres delete 작업이 12분 이상 실행되고 있기 때문입니다. 게시글은 60만 개 미만, 사용자는 4천 명 미만이라 데이터베이스가 크지 않습니다. 아, 잠깐. postgres_data 디렉토리가 28GB나 됩니다.

VACUUM VERBOSE ANALYZE;를 실행했습니다.

다음과 같이 실행했습니다:

discourse=# SELECT checkpoints_timed, checkpoints_req FROM pg_stat_bgwriter; 
 checkpoints_timed | checkpoints_req 
-------------------+-----------------
                 6 |              20

현재 동시 재인덱싱(reindex concurrently)을 시도하고 있습니다. vacuum과 재인덱싱이 도움이 될지 지켜보겠습니다.

제이, 감사합니다. 제가 도와드릴 일이 있으면 말씀해 주세요.

긴 실행 중인 쿼리의 전체 SQL을 공유해 주세요.

그걸 어디서 찾을 수 있나요?

마이그레이션이 로그를 출력하지 않습니다. 리빌드의 마지막 줄은 다음과 같습니다.

I, [2023-12-04T22:33:33.759401 #1]  INFO -- : > cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' 

방금 재시작한 인스턴스의 전체 로그를 준비하고 있습니다.

컨테이너에 진입한 후 postgres 사용자로 전환하고, psql을 실행한 다음 다음 쿼리를 실행하세요.

SELECT pid, age(clock_timestamp(), query_start), usename, query 
FROM pg_stat_activity 
WHERE query != '<IDLE>' AND query NOT ILIKE '%pg_stat_activity%' 
ORDER BY query_start desc;