# 최적 성능을 위한 SQLite on Rails의 방법과 이유

> Clean Markdown view of GeekNews topic #16743. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=16743](https://news.hada.io/topic?id=16743)
- GeekNews Markdown: [https://news.hada.io/topic/16743.md](https://news.hada.io/topic/16743.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2024-09-13T09:58:18+09:00
- Updated: 2024-09-13T09:58:18+09:00
- Original source: [fractaledmind.github.io](https://fractaledmind.github.io/2024/04/15/sqlite-on-rails-the-how-and-why-of-optimal-performance/)
- Points: 1
- Comments: 1

## Topic Body

- 지난 1년 동안 SQLite를 사용하여 Rails 애플리케이션을 성능 좋고 안정적으로 실행하는 방법을 깊이 이해하려고 노력해왔음
- 이 과정에서 여러 가지 교훈을 배웠으며, 이를 공유하고자 함
- 문제의 원인과 해결 방법을 설명할 것임

### SQLite와 Rails의 문제점

- 기본적으로 SQLite를 사용한 Rails 애플리케이션은 바로 사용할 수 있는 상태가 아님
- 약간의 조정과 미세 조정을 통해 성능 좋고 안정적인 애플리케이션을 만들 수 있음
- Rails 8에서는 기본 설정만으로도 프로덕션 준비가 완료된 상태가 되도록 목표를 설정함

### 데모 애플리케이션 "Lorem News"

- "Lorem News"라는 데모 애플리케이션을 사용하여 문제와 해결책을 설명할 것임
- 이 애플리케이션은 Hacker News의 클론으로, 사용자들이 게시물과 댓글을 작성할 수 있음

### 성능 테스트

- `oha` 로드 테스트 CLI와 애플리케이션 내 벤치마킹 경로를 사용하여 성능을 테스트함
- 단일 요청과 동시 요청을 통해 성능을 측정함

### 주요 문제: `SQLITE_BUSY` 예외

- SQLite는 한 번에 하나의 쓰기 작업만 허용하기 위해 쓰기 잠금을 사용함
- 여러 연결이 동시에 쓰기 잠금을 시도하면 `SQLITE_BUSY` 예외가 발생함
- 이 문제를 해결하기 위해 즉시 트랜잭션을 사용해야 함

### 즉시 트랜잭션

- 기본적으로 SQLite는 지연된 트랜잭션 모드를 사용함
- 즉시 트랜잭션을 사용하면 쓰기 잠금을 즉시 시도하고 실패 시 재시도할 수 있음
- `sqlite3-ruby` gem을 사용하여 기본 트랜잭션 모드를 즉시 모드로 설정할 수 있음

### 타임아웃 설정

- `database.yml` 파일에서 타임아웃 설정을 통해 `SQLITE_BUSY` 예외를 줄일 수 있음
- SQLite의 `busy_timeout` 설정을 사용하여 쓰기 잠금을 재시도할 수 있음

### GVL(글로벌 VM 잠금) 문제

- `sqlite3-ruby` gem은 SQLite의 C 코드를 호출할 때 GVL을 해제하지 않음
- 이는 동시성 성능을 저하시킴
- `busy_handler`를 사용하여 GVL을 해제하고 성능을 개선할 수 있음

### `busy_timeout` 재구현

- `busy_timeout`을 재구현하여 모든 쿼리가 동일한 빈도로 재시도하도록 설정함
- 이는 오래된 쿼리가 타임아웃되지 않도록 함

### 성능 개선

- 성능을 개선하기 위해 다음과 같은 설정을 적용해야 함
  - 즉시 트랜잭션 사용
  - 타임아웃 설정
  - `busy_handler` 사용
  - WAL(Write-Ahead Logging) 모드 사용
  - 읽기/쓰기 연결 풀 분리

### GN⁺의 정리

- SQLite를 사용한 Rails 애플리케이션의 성능 문제와 해결책을 다룸
- 즉시 트랜잭션, 타임아웃 설정, GVL 해제, WAL 모드 사용, 읽기/쓰기 연결 풀 분리 등의 방법을 통해 성능을 개선할 수 있음
- 이 기사는 SQLite와 Rails를 사용하는 개발자들에게 매우 유용할 것임
- 유사한 기능을 가진 다른 프로젝트로는 PostgreSQL과 MySQL을 추천함

## Comments



### Comment 28888

- Author: neo
- Created: 2024-09-13T09:58:18+09:00
- Points: 1

###### [Hacker News 의견](https://news.ycombinator.com/item?id=41513648) 
- **Oldmoe의 Litestack 프로젝트 소개**
  - SQLIte와 Rails를 사용하는 사람들은 Oldmoe의 Litestack 프로젝트를 확인할 필요가 있음
  - Litestack은 SQLite의 강력함을 활용하여 웹 애플리케이션 데이터 인프라를 제공하는 Ruby gem임
  - SQL 데이터베이스, 빠른 캐시, 강력한 작업 큐, 신뢰할 수 있는 메시지 브로커, 전체 텍스트 검색 엔진, 메트릭스 플랫폼을 하나의 패키지로 제공함
  - 현재 프로젝트에서 사용 중이며 매우 만족스러움

- **상세한 기사 작성에 대한 감사**
  - SQLite 웹 애플리케이션을 확장하려는 사람들에게 유용한 정보임
  - Rails를 넘어 다른 프레임워크에서도 적용 가능함
  - 작가에게 감사함

- **SQLite 관련 작업을 하는 사람들에게 추천**
  - 사용하는 언어나 프레임워크와 상관없이 SQLite 관련 작업을 하는 사람들은 이 기사를 읽어야 함
  - 몇 년 전에는 직접 해결해야 했던 문제들을 다루고 있음
  - 작가에게 감사함

- **FOSS 분석 시스템에 대한 질문**
  - 설치가 쉬운 FOSS 분석 시스템을 만들고 있음
  - 이벤트 데이터를 별도의 SQLite 데이터베이스에 보내어 메인 앱의 데이터와 분리하려고 함
  - 초당 1000개 이상의 이벤트를 처리할 수 있는 확장성에 대한 우려가 있음
  - 서버 메모리에 이벤트를 저장하고 매초 한 번씩 일괄적으로 쓰는 방법을 고려 중임
  - SQLite의 많은 DB 쓰기 문제를 해결할 수 있는 합리적인 방법인지 의견을 구함

- **sqlite3-ruby gem의 GVL 문제**
  - sqlite3-ruby gem은 SQLite 호출 시 GVL을 해제하지 않음
  - 이는 대부분 합리적인 결정으로 보임
  - Python 확장에서는 다른 방식으로 설계되었을 가능성이 있음
  - extralite gem은 블로킹 중 GVL을 해제하며, 일반적으로 더 빠르고 동시성 문제도 없음

- **개인 웹서비스 설정**
  - 개인 웹서비스에서 사용하는 몇 가지 설정:
    - `PRAGMA journal_mode = WAL`
    - `PRAGMA busy_timeout = 5000`
    - `PRAGMA synchronous = NORMAL`
    - `PRAGMA cache_size = 1000000000`
    - `PRAGMA foreign_keys = true`
    - `PRAGMA temp_store = memory`
    - `BEGIN IMMEDIATE` 트랜잭션 사용

- **Django에 대한 질문**
  - 이 기사는 훌륭함
  - Django에 대한 유사한 솔루션이 있는지 궁금함
  - ArchiveBox는 Django를 통해 SQLite를 사용하며, Rails에서 언급된 문제를 자주 겪음
  - 앱의 다른 채널을 통해 모든 쓰기를 직렬화하지 않는 SQLite 레이어 솔루션이 있으면 좋겠음

- **`busy_timeout` 기본 설정에 대한 의문**
  - 매우 유익하고 잘 작성된 기사임
  - 기본 `busy_timeout` 메서드가 오래된 쿼리를 벌주는 지연을 가지는 이유가 궁금함
  - 왜 이것이 기본 설정으로 의미가 있는지 궁금함

- **SQLite와 Rails 사용에 대한 의견**
  - SQLite와 Rails를 좋아하지만, 이는 MS Access를 프로덕션 환경에서 사용하는 것과 유사함

- **Rails 통합 문제 해결에 대한 감사**
  - 통합 문제를 해결하고 다른 사람들을 도와주는 것을 항상 기쁘게 생각함
  - 이러한 수정 사항이 기본 Rails 설정에 포함되기를 바람
  - Rails 앱을 운영하며, 몇 년 전 Postgres로 전환하여 매우 만족하고 있음
  - 여전히 대안이 있는 것은 좋으며, 다른 작업에 SQLite를 사용함
