lobste.rs, MariaDB에서 SQLite로 전환
2 days ago
5
- lobste.rs는 MariaDB에서 SQLite로 전환한 뒤 월요일 트래픽 급증까지 안정적으로 처리했으며, CPU·메모리 사용량 감소와 더 빠른 체감 응답성을 확인함
- 별도 MariaDB VPS를 내리면 VPS 비용이 절반으로 줄어들고, 2019년 시작된 마이그레이션 과제도 마무리됨
- 첫 배포에서는 읽기 전용 트래픽만으로 모든 CPU가 100%에 도달해 롤백했으나, 대형 테이블의 전체 테이블 스캔 2건과 N+1 문제를 수정한 뒤 재배포에 성공함
- SQLite 사용자 정의 함수로 regexp·if·stddev를 구현하는 한편, unsigned bigint 미지원과 ASCII만 처리하는 NOCASE 등 호환성 제약을 해결해야 했음
- 프로덕션 데이터베이스에 접근하지 않고 기반 DB를 바꾸려면 현실적인 크기의 테스트 데이터, 테스트 스위트, 배포·롤백 체크리스트와 긴밀한 협업이 필요함
2019년 논의에서 SQLite 전환까지
- 마이그레이션 논의는 2019년 이슈 #539에서 시작됨
- 2025년 8월의 첫 번째 PR은 작업이 중단된 뒤 GitHub에서 오래된 PR로 닫혀 다시 열 수 없었음
- 두 번째 PR에는 성능 테스트, 자체 DB 간 마이그레이션 스크립트, 데이터 무결성 관련 디버깅이 포함됨
- 기존 MariaDB/MySQL→SQLite 변환 스크립트 가운데 요구를 충족하는 것이 없어 별도 스크립트를 작성함
첫 배포 실패와 성능 병목 수정
- 2월 21일 첫 배포는 배포 체크리스트를 준비해 진행했지만, 배포 직후 읽기 전용 상태의 트래픽만으로 모든 CPU가 100% 에 도달함
- 원인을 찾지 못해 롤백함
- 프로덕션 DB에 접근할 수 없어 실제 성능 문제를 사전에 재현하기 어려웠음
- 실패 이틀 뒤 세 번째이자 최종 PR을 열어 검색 관련 문제를 수정하고, 실제 lobsters 데이터의 절반 크기를 로컬에 만드는 대량 데이터 생성 스크립트를 추가함
- 데이터를 생성하는 데 일주일이 걸림
- 첫 배포의 병목은 대형 테이블에서 두 쿼리가 일으킨 전체 테이블 스캔과 별도의 N+1 문제였음
- 이를 해결한 변경 1, 변경 2, 변경 3를 반영함
- 추가 성능 문제를 추적할 수 있도록 배포 당일 아침 느린 쿼리 로그를 더함
재배포 결과와 운영 비용 절감
- 7월 11일 두 번째 배포에서는 배포·롤백 체크리스트를 다시 준비했으며, 전환 후에도 사이트가 정상 운영되고 CPU와 메모리 사용량도 안정적으로 유지됨
- 사이트 지표와 IRC를 감시하면서 보고된 문제를 수정 1, 수정 2로 즉시 처리함
- 월요일 트래픽 급증에서도 문제가 없었고, CPU·메모리 사용량 감소와 더 빠른 체감 응답성을 확인함
- MariaDB VPS를 종료하면 VPS 비용이 절반으로 줄어들며, 마이그레이션 이슈도 닫힘
MariaDB와 달랐던 SQLite의 제약
- SQLite gem의 사용자 정의 함수(UDF) 지원을 이용해 SQLite에 없던 regexp, if, stddev를 구현함
- SQL 마이그레이션을 위한 우회 처리를 과도하게 추가하지 않아도 됐음
- MariaDB에서 일부 ID에 사용하던 unsigned bigint를 SQLite가 지원하지 않아 bigint로 변경함
- 정렬 규칙도 MariaDB보다 제한적임
- MariaDB에서는 utf8mb4_general_ci를 사용했지만 SQLite에서는 NOCASE를 적용함
- NOCASE는 전체 UTF 대소문자 접기를 지원하지 않고 ASCII 문자만 처리함
- SQLite 전체 텍스트 검색 테이블에는 기본값이 아닌 권장 방식인 Contentless-Delete Tables가 적합함
- Rails의 기본 PRAGMA 설정은 lobsters에서 정상적으로 작동함
- 데이터베이스 마이그레이션은 DB별로 달라 기존 마이그레이션을 old_migrations 디렉터리로 옮기고 db:migrate가 계속 작동하도록 함
테스트와 협업에서 얻은 교훈
- lobsters 코드베이스에서는 검색 파서와 렌더링 속도를 높이는 해킹인 heinous_inline_partials를 확인함
- 테스트 스위트 덕분에 대규모 수동 테스트 없이 SQLite 전환의 정확성을 검증할 수 있었음
- 참여자 사이의 원활한 소통이 마이그레이션 성공을 좌우함
- 프로덕션 DB에 접근하지 못한 상태에서 기반 데이터베이스를 교체하기는 매우 어려웠음
- 같은 작업을 다시 한다면 사전에 현실적인 데이터 규모를 준비해야 함
- 테스트 중 전체 테이블 스캔이 발생하면 실패하도록 설정할 수 있었다면 첫 배포의 성능 문제를 미리 잡을 수 있었음
- 프로덕션과 유사한 데이터셋을 직접 작성하거나 일주일씩 기다리지 않고 쉽게 만들 수 있는 도구가 필요함
-
Homepage
-
Tech blog
- lobste.rs, MariaDB에서 SQLite로 전환