SQLite в проде, год спустя
Год назад я выкинул Postgres из своего пет-проекта и поставил один файл .db
рядом с бинарником. С тех пор база пережила два переезда, четыре релиза и одно
бухое воскресенье. Делюсь что выяснилось.
Что я ожидал получить
Ноль операционной нагрузки. Никаких RDS, никаких pg_hba.conf, никаких
странных таймаутов в три ночи. Бэкап — это cp. Миграция — это scp.
Восстановление — это уже выученный наизусть пароль от ssh.
Что получил на самом деле
Всё то же самое, плюс одна неожиданная штука: я наконец начал думать о схеме данных до, а не после. Когда база — это файл, который ты можешь скачать и открыть в DB Browser за две секунды, ленивые миграции «потом починим» внезапно становятся непростительно ленивыми. Файл лежит перед тобой целиком, врать ему некуда.
Где всё-таки прижало
Записей было немного, но они шли пачками. По дефолту SQLite отдаёт SQLITE_BUSY,
как только два писателя сталкиваются лбами. Лечится одной строчкой:
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
WAL разводит читателей и писателя по разным углам, а busy_timeout говорит
драйверу не паниковать, а подождать. После этого «конкурентность» в моём
масштабе (десятки запросов в секунду, не тысячи) перестала быть темой для
разговора вообще.
Второе, что укусило, — это типизация. SQLite хранит что положишь, а не что
объявил. Строка в колонке INTEGER? Пожалуйста. Спасает либо строгий режим
(STRICT таблицы), либо дисциплина на уровне приложения. Я выбрал STRICT и ни
разу не пожалел.
Бэкап, который не врёт
cp живого файла под нагрузкой — это лотерея. Правильный способ ровно один:
sqlite3 app.db ".backup '/backups/app-$(date +%F).db'"
Эта команда снимает консистентный снапшот, не блокируя писателей надолго.
Кладёшь в cron, рядом — restic в S3-совместимое хранилище, и спишь спокойно.
Весь «бэкап-пайплайн» — пять строк в скрипте.
Итого
SQLite — это не «база для бедных». Это осознанный выбор в пользу простоты, когда ты честно понимаешь свой профиль нагрузки. Один файл, ноль демонов, бэкап копированием. Postgres вернётся в мою жизнь в тот день, когда мне реально понадобится то, что умеет только он. Пока — не понадобился.