🗄️ БАЗЫ ДАННЫХ¶
БД — структурированное хранилище данных. СУБД — ПО, которое создаёт БД, даёт доступ (SQL и др.), обеспечивает целостность и безопасность.
Status: Draft
1. Типы БД
Три модели, с которыми чаще всего сталкиваются в проде.
Реляционные
Данные в таблицах (строки × столбцы), связи через PK / FK, запросы на SQL.
| Плюсы | целостность, JOIN, транзакции (ACID), зрелые инструменты |
| Минусы | схема жёстче; горизонтальный scale сложнее, чем у многих NoSQL |
| Примеры | PostgreSQL, MySQL, SQL Server, Oracle, SQLite |
Первичный ключ (PK) — однозначно идентифицирует строку. Внешний ключ (FK) — ссылка на PK другой таблицы; СУБД проверяет ссылочную целостность.
Key-value
Пары ключ → значение; значение — что угодно (строка, JSON, бинарь).
| Плюсы | скорость, простая модель, гибкие значения |
| Минусы | слабые запросы по «содержимому»; логика часто в приложении |
| Примеры | Redis, etcd, DynamoDB (как KV-слой) |
Документоориентированные
Хранят документы (часто JSON-подобные) в коллекциях; схема гибкая — поля могут отличаться между документами.
| Плюсы | гибкая модель, удобно для вложенных структур |
| Минусы | целостность и JOIN’ы слабее классического SQL |
| Примеры | MongoDB, CouchDB |
db.users.find({"name": "Daniel"}).count()
2. SQL-шпаргалка
Диалекты отличаются (MySQL, PostgreSQL/PL/pgSQL, T-SQL…), база SELECT общая.
SELECT и фильтры
SELECT col1, col2 AS alias
FROM table_name
WHERE status IN ('a', 'b')
AND price BETWEEN 100 AND 500
AND name IS NOT NULL
AND email LIKE '%@example.com'
ORDER BY created_at DESC
LIMIT 100;
DISTINCT— уникальные строкиAND/OR/NOT— логика вWHERE- Сравнение с
NULL— толькоIS NULL/IS NOT NULL, не=
JOIN
Связка таблиц по ключу:
SELECT u.name, o.total
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.total > 100;
| Тип | Смысл |
|---|---|
INNER JOIN |
только совпавшие строки |
LEFT JOIN |
все слева + совпадения справа (или NULL) |
RIGHT JOIN |
зеркало LEFT (реже) |
FULL JOIN |
все с обеих сторон (есть в PostgreSQL) |
GROUP BY, агрегаты, HAVING
SELECT home_type, AVG(price) AS avg_price, COUNT(*) AS n
FROM rooms
GROUP BY home_type
HAVING AVG(price) > 50
ORDER BY n DESC;
Агрегаты: COUNT, SUM, AVG, MIN, MAX.
Порядок выполнения (упрощённо):
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
WHERE фильтрует строки до группировки; HAVING — группы после.
3. PostgreSQL: права
Практика: отдельный пользователь с минимальными правами (часто read-only для аналитики).
RO-пользователь
CREATE USER analytics WITH PASSWORD '…';
GRANT CONNECT ON DATABASE sedo TO analytics;
GRANT USAGE ON SCHEMA public TO analytics;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO analytics;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO analytics;
Только CONNECT + USAGE + SELECT — без INSERT/UPDATE/DELETE/CREATE.
Проверка привилегий (psql)
| Команда | Что смотрит |
|---|---|
\dp |
права на таблицы / views / sequences |
\dn+ |
схемы и права (U = USAGE, C = CREATE) |
\ddp |
default privileges для новых объектов |
В \dp вид analytics=r/sedo — у analytics есть SELECT (r), выдал sedo.
Буквы: r SELECT, w INSERT, u UPDATE, d DELETE, …
Postgres Pro (кратко)
Форк PostgreSQL (Postgres Professional): коммерческая поддержка, доп. модули, сертификация ФСТЭК — часто в контексте импортозамещения.
Для ops-базы достаточно знать: синтаксис/репликация близки к PostgreSQL; отличия — в Enterprise-фичах (бэкап, сжатие, мультимастер и т.д.), не в «другом SQL».
4. HA PostgreSQL (Patroni)
Типичный стек: Patroni (мастер/failover) + etcd (DCS) + HAProxy (точка входа) + Keepalived (VIP).
Роли компонентов
| Компонент | Роль |
|---|---|
| Patroni | Управляет PostgreSQL, репликацией и авто-failover |
| etcd | Хранит метаданные кластера (кто master) |
| HAProxy | Клиенты ходят сюда; проксирует на текущего master |
| Keepalived | Держит VIP на активном HAProxy |
Patroni (фрагмент)
На каждой PG-ноде свой name / IP. Пример pg_node_1:
scope: pg_cluster
namespace: /pg_cluster/
name: pg_node_1
restapi:
listen: 192.168.1.101:8008
connect_address: 192.168.1.101:8008
etcd:
hosts: 192.168.1.201:2379,192.168.1.202:2379,192.168.1.203:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
postgresql:
use_pg_rewind: true
parameters:
max_connections: 200
shared_buffers: 256MB
synchronous_commit: "on"
initdb:
- encoding: UTF8
- data-checksums
postgresql:
listen: 192.168.1.101:5432
connect_address: 192.168.1.101:5432
data_dir: /var/lib/postgresql/12/main
authentication:
replication:
username: replicator
password: secret
superuser:
username: postgres
password: supersecret
parameters:
hot_standby: "on"
etcd, HAProxy, Keepalived
etcd (пример env одной ноды):
ETCD_NAME=etcd1
ETCD_INITIAL_CLUSTER=etcd1=http://192.168.1.201:2380,etcd2=http://192.168.1.202:2380,etcd3=http://192.168.1.203:2380
ETCD_INITIAL_ADVERTISE_PEER_URLS=http://192.168.1.201:2380
ETCD_LISTEN_PEER_URLS=http://192.168.1.201:2380
ETCD_LISTEN_CLIENT_URLS=http://192.168.1.201:2379
ETCD_ADVERTISE_CLIENT_URLS=http://192.168.1.201:2379
HAProxy — TCP на 5432, health-check Patroni /master (порт 8008):
frontend postgresql
bind *:5432
default_backend postgresql_cluster
backend postgresql_cluster
mode tcp
option httpchk GET /master
http-check expect status 200
default-server inter 3s fall 3 rise 2
server pg1 192.168.1.101:5432 check port 8008
server pg2 192.168.1.102:5432 check port 8008
server pg3 192.168.1.103:5432 check port 8008 backup
Keepalived — VIP 192.168.1.100 (на backup-ноде priority ниже):
vrrp_instance haproxy_vip {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass keepalive
}
virtual_ipaddress {
192.168.1.100
}
}
Клиенты: psql -h 192.168.1.100 -U postgres -d mydb
FAQ failover
- Кто станет master? — реплика с наибольшим LSN (прогресс WAL), по правилам Patroni
- Кто сейчас master? —
curl http://<node>:8008/master - Кластер «завис» — проверить etcd;
systemctl restart etcd;patronictl list/ restart node - Ускорить failover — уменьшить
ttl/loop_wait/retry_timeout(осторожнее с ложными срабатываниями) - Без Patroni? — можно, но promote/failover руками (
pg_ctl promote)
Вопросы
В разработке..