Что такое SQLite: самая используемая СУБД в мире
SQLite — самая распространённая база данных на планете. Она установлена на каждом iPhone и Android-смартфоне, в каждом браузере Chrome и Firefox, в Windows 10/11, macOS, в Python стандартной библиотеке. По оценкам разработчиков SQLite, активных копий базы более одного триллиона — больше, чем любого другого программного обеспечения в мире.
При этом SQLite отличается от всех привычных СУБД: у неё нет сервера, нет сетевых подключений, нет пользователей и паролей. Вся база данных — один файл на диске.
Архитектура SQLite: почему один файл
Большинство СУБД (PostgreSQL, MySQL, MongoDB) работают как клиент-серверное приложение: отдельный процесс-сервер слушает соединения, получает запросы по сети и возвращает результаты. Это требует настройки, потребляет оперативную память даже в простое и добавляет задержку на каждый запрос.
SQLite устроена иначе: это библиотека, которая встраивается непосредственно в ваше приложение. Когда вы пишете sqlite3.connect('database.db'), библиотека открывает файл напрямую и работает с ним через системные вызовы ОС — без какого-либо сетевого взаимодействия.
Традиционная СУБД: SQLite:
┌──────────┐ ┌────────────────────────┐
│ App │──TCP──►DB │ App + SQLite lib │
│ │◄──TCP──Server │ │
└──────────┘ │ ┌──────────────────┐ │
│ │ database.db │ │
│ └──────────────────┘ │
└────────────────────────┘
Преимущества встроенной архитектуры:
- Нет задержки сети — запрос выполняется в процессе приложения
- Нет отдельного сервиса для настройки и поддержки
- Файл базы данных можно скопировать, перенести, заархивировать как обычный файл
- Работает без прав администратора
- Нулевая конфигурация
SQLite поддерживает полный SQL
Распространённое заблуждение: «SQLite — это не настоящая база данных». На деле SQLite реализует большую часть стандарта SQL-92 и многие расширения:
-- SQLite поддерживает транзакции ACID
BEGIN TRANSACTION;
INSERT INTO orders (user_id, total) VALUES (42, 1500.00);
INSERT INTO order_items (order_id, product_id, qty) VALUES (last_insert_rowid(), 7, 2);
COMMIT;
-- Window Functions (с SQLite 3.25.0, 2018)
SELECT
name,
salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC) as rank_in_dept
FROM employees;
-- CTE (Common Table Expressions)
WITH RECURSIVE categories AS (
SELECT id, name, parent_id FROM category WHERE id = 1
UNION ALL
SELECT c.id, c.name, c.parent_id
FROM category c
JOIN categories p ON c.parent_id = p.id
)
SELECT * FROM categories;
-- JSON (с SQLite 3.38.0)
SELECT json_extract(metadata, '$.tags[0]') as first_tag
FROM articles
WHERE json_extract(metadata, '$.published') = true;
SQLite не поддерживает: RIGHT JOIN (используйте LEFT JOIN в обратном порядке), ALTER TABLE с полным набором операций, вложенные транзакции (есть SAVEPOINT), оконный тип ROWS UNBOUNDED.
WAL-режим: как SQLite справляется с конкурентностью
Главное ограничение базового SQLite — блокировка файла при записи. Только один процесс может записывать данные одновременно. Это решается WAL (Write-Ahead Logging) режимом:
-- Включить WAL (делать один раз при старте)
PRAGMA journal_mode=WAL;
-- Дополнительные оптимизации для продакшна
PRAGMA synchronous=NORMAL; -- быстрее, безопасно с WAL
PRAGMA cache_size=-64000; -- 64MB кэш страниц
PRAGMA foreign_keys=ON; -- включить FK по умолчанию выключены
PRAGMA busy_timeout=5000; -- ожидать 5 секунд при блокировке
В WAL-режиме:
- Несколько читателей работают параллельно с одним писателем
- Читатели не блокируют писателя и наоборот
- Производительность записи возрастает значительно
Практический предел WAL-режима: ~10,000-50,000 записей в секунду на SSD. Для большинства web-приложений этого более чем достаточно.
Ренессанс SQLite в 2026 году
SQLite долго считался «не для продакшна». В 2026 году ситуация изменилась — появилось несколько инструментов, которые устраняют исторические ограничения:
Turso (libSQL): Распределённая SQLite с репликацией по нескольким регионам. Форк SQLite на Rust с конкурентной записью, векторным поиском и поддержкой WASM. 500 баз данных бесплатно.
Cloudflare D1: Managed SQLite в сети Cloudflare. Автоматическая репликация, работает в Workers без TCP. Запросы выполняются ближайшему к пользователю дата-центру.
LiteFS: Репликация SQLite через FUSE-файловую систему от Fly.io. Позволяет иметь read-реплики в разных регионах при single-writer primary.
PocketBase: Готовый BaaS на SQLite. За раз закрывает нужды в БД, Auth, Storage и API.
Litestream: Непрерывная репликация SQLite в S3 в реальном времени. Решает проблему DR (disaster recovery) — восстановление занимает секунды.
# Litestream: репликация SQLite в S3 в реальном времени
litestream replicate /data/database.db s3://my-bucket/db
Когда SQLite — правильный выбор
SQLite превосходит PostgreSQL и MySQL в конкретных сценариях:
Мобильные приложения: SQLite встроена в Android (Room Database) и iOS (Core Data). Нет альтернативы для локального хранения на устройстве.
Десктопные приложения: Electron, Tauri, Qt приложения. SQLite хранит настройки, кэш, данные пользователя без установки СУБД.
Один сервер, предсказуемая нагрузка: Если ваш проект работает на одном VPS и не требует масштабирования — SQLite быстрее PostgreSQL из-за отсутствия сетевого overhead.
PocketBase и аналоги: Если используете PocketBase, SQLite — встроенная. Управлять отдельной БД не нужно.
Edge-вычисления: Cloudflare D1, Turso дают SQLite на edge-узлах по всему миру.
Тестирование: SQLite-инстанс в памяти :memory: поднимается за миллисекунды. Идеально для unit-тестов против реальной БД.
Файлы как архивы: SQLite-файл — отличный формат для дистрибьюции данных вместо CSV. Запросы через SQL, не парсинг строк.
Когда SQLite — неправильный выбор
Не используйте SQLite если:
- Несколько серверов пишут в одну базу (горизонтальное масштабирование)
- Интенсивная конкурентная запись (>100 одновременных писателей)
- База данных больше 100-200 GB (начинает тормозить, хотя технически поддерживает до 281 TB)
- Нужны специфические PostgreSQL-фичи: PostGIS, pgvector, row-level security, advanced types
- Команда работает из разных хостов с прямым доступом к БД
Сравнение SQLite с PostgreSQL и MySQL
| Параметр | SQLite | PostgreSQL | MySQL | |---|---|---|---| | Тип | Встроенная | Клиент-серверная | Клиент-серверная | | Настройка | Нулевая | Умеренная | Умеренная | | Конкурентная запись | Ограниченная (WAL) | Высокая (MVCC) | Высокая | | Транзакции | ACID | ACID | ACID (InnoDB) | | Масштабирование | Вертикальное | Вертикальное + реплики | Вертикальное + реплики | | JSON-поддержка | Базовая | Отличная (JSONB) | Базовая | | Полнотекстовый поиск | Базовый (FTS5) | Хороший | Базовый | | Геоданные | Нет | PostGIS | Базово | | Использование RAM | Минимальное | 512MB+ | 256MB+ | | Портативность | Один файл | Директория данных | Директория данных | | Типизация | Слабая (type affinity) | Строгая | Строгая | | Лучше для | Embedded, edge, MVP | Production web, SaaS | Legacy, WordPress |
SQLite в продакшне: практические советы
SQLite в продакшне работает, если соблюдать несколько правил:
# Python: настройка SQLite для продакшна
import sqlite3
def get_db_connection(db_path: str) -> sqlite3.Connection:
conn = sqlite3.connect(db_path, check_same_thread=False)
conn.row_factory = sqlite3.Row # словари вместо кортежей
# Обязательные PRAGMA для продакшна
conn.execute("PRAGMA journal_mode=WAL")
conn.execute("PRAGMA synchronous=NORMAL")
conn.execute("PRAGMA foreign_keys=ON")
conn.execute("PRAGMA cache_size=-32000") # 32MB кэш
conn.execute("PRAGMA busy_timeout=10000") # 10 секунд таймаут
conn.execute("PRAGMA temp_store=MEMORY")
return conn
// Node.js / Bun.js: лучшие практики
import Database from 'better-sqlite3'
// или import { Database } from 'bun:sqlite'
const db = new Database('production.db', { readonly: false })
// WAL mode
db.pragma('journal_mode = WAL')
db.pragma('synchronous = NORMAL')
db.pragma('foreign_keys = ON')
db.pragma('busy_timeout = 10000')
db.pragma('cache_size = -32000')
// Всегда используйте prepared statements для безопасности
const getUser = db.prepare('SELECT * FROM users WHERE id = ?')
const user = getUser.get(userId)
Бэкап SQLite: атомарность важна
SQLite-бэкап через простое копирование файла (cp database.db backup.db) может дать повреждённый бэкап, если в момент копирования шла запись. Правильные методы:
# 1. Через SQLite CLI (безопасно при активной записи)
sqlite3 database.db ".backup backup.db"
# 2. Через Litestream (непрерывная репликация в S3)
litestream replicate /data/database.db s3://bucket/database
# 3. Через dbsend.ru (автоматически, с атомарностью)
dbsend backup \
--db=sqlite:///data/database.db \
--destination=s3://bucket/sqlite \
--schedule="*/15 * * * *" \ # каждые 15 минут
--keep=200
dbsend.ru использует встроенный SQLite Backup API для атомарного снимка базы без блокировки записей. Бэкап создаётся без даунтайма.
FAQ
Можно ли использовать SQLite в продакшне в 2026 году?
Да, и это не редкость. Basecamp использует SQLite в продакшне для нескольких своих сервисов (сам DHH публично об этом писал). PocketBase построен на SQLite. Cloudflare D1 — SQLite в глобальной сети. Ключевые условия: один основной сервер (не горизонтальное масштабирование), WAL-режим включён, настроены автоматические бэкапы.
Насколько большой может быть SQLite база?
Теоретический максимум — 281 TB. Практически: до 1-5 GB работает отлично, до 50 GB — хорошо, до 200 GB — нормально на быстром SSD. При большем объёме производительность сложных запросов деградирует. Для баз более 50 GB рассмотрите PostgreSQL или Turso с шардингом.
SQLite потокобезопасна?
С ключом компиляции SQLITE_THREADSAFE=1 (по умолчанию в большинстве дистрибутивов) SQLite поддерживает несколько потоков. В serialized-режиме только один поток выполняет запрос в момент времени. WAL-режим позволяет нескольким читателям работать параллельно с одним писателем.
Чем SQLite отличается от Turso?
Turso — это libSQL, форк SQLite на Rust с дополнительными возможностями: конкурентная запись (решена single-writer проблема), встроенные реплики (embedded replicas), векторный поиск, HTTP API, WASM-поддержка. Turso Cloud — managed сервис поверх libSQL. Файловый формат .db полностью совместим с SQLite.
Есть ли у SQLite полнотекстовый поиск?
Да, через расширение FTS5 (Full-Text Search). Индексирует текстовые столбцы и поддерживает поиск по ключевым словам, фразовый поиск, близость слов:
CREATE VIRTUAL TABLE articles_fts USING fts5(title, content);
SELECT * FROM articles_fts WHERE articles_fts MATCH 'база данных';
Для русского языка качество поиска хуже, чем у PostgreSQL с russian tsearch-конфигурацией. Для продакшн-поиска по русскому тексту рассмотрите Meilisearch.
Как правильно мигрировать схему в SQLite?
SQLite поддерживает только ограниченный ALTER TABLE (добавление колонки, переименование). Для сложных миграций (удаление колонки, изменение типа) нужно создать новую таблицу и перенести данные:
-- Добавление колонки — легко
ALTER TABLE users ADD COLUMN avatar_url TEXT;
-- Удаление колонки — через пересоздание
CREATE TABLE users_new AS SELECT id, name, email FROM users;
DROP TABLE users;
ALTER TABLE users_new RENAME TO users;
Для автоматизации используйте Drizzle Migrate или Flyway.