fix(db): /dev/shm боевого postgres — 64 МБ умолчания Docker на 1 ГиБ
All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 12s
CI / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped

Параллельные планы Постгреса размещают DSM-сегменты в /dev/shm
(dynamic_shared_memory_type=posix). Контейнеру БД никто не задавал shm_size,
поэтому там держалось умолчание Docker — 64 МБ, и запросы Объектива падали
с psycopg.errors.DiskFull «could not resize shared memory segment».
Текст ошибки называет НЕ тот ресурс: на разделе 28 ГБ свободно, кончался
именно /dev/shm.

Замеры на проде 2026-08-10 (не рекомендация из интернета):
  постоянный расход  ~9.8 МиБ (DSA кумулятивной статистики pgstat)
  один параллельный  ~15.4 МиБ (3 одновременных → 55.9 МиБ из 64)
  → 4-й одновременный запрос не влезает; ровно это и наблюдалось
    (6 отказов за 1.2 с из двух backend-процессов)

Нижняя граница: 128 МиБ покрывают лишь ~7-8 одновременных, а потолок
celery (--concurrency=8) плюс request-path даёт ~12 → минимум 256 МиБ.
Верхняя: /dev/shm это tmpfs, страницы выделяются по факту, поэтому
значение — потолок, а не резерв; на хосте 11 ГиБ RAM (свободно ~6),
2 ГиБ я бы не переходил. 1 ГиБ = ~65 таких запросов, ~5x запаса.

Локальная проверка A/B (postgres:16, GUC как на проде, различается только
--shm-size): 6 одновременных параллельных запросов
  64m → 4 отказа, пик 57.3 МиБ (упёрлись в лимит)
  1g  → 0 отказов, пик 113.3 МиБ (реальный спрос вдвое выше 64 МиБ)

Refs #2812
This commit is contained in:
bot-backend 2026-08-10 15:30:06 +05:00
parent 5ee4126ed0
commit 6ab359a127

View file

@ -78,6 +78,16 @@ services:
image: postgis/postgis:16-3.4
logging: *default-logging
restart: unless-stopped
# #2812: /dev/shm под dynamic_shared_memory_type=posix. Умолчание Docker — 64 МБ,
# и параллельные планы кладут туда свои DSM-сегменты. Прод-замер 2026-08-10:
# база постоянно держит ~9.8 МиБ (DSA кумулятивной статистики pgstat), один
# параллельный запрос Объектива берёт ~15.4 МиБ → 4-й одновременный не влезает
# в 64 МиБ и падает `DiskFull: could not resize shared memory segment`. Ровно это
# и случилось: 6 отказов за 1.2 с (market_metrics / sales_series / special_indices).
# 1 ГиБ = ~65 таких запросов; потолок celery (--concurrency=8) + request-path ≈ 12.
# tmpfs выделяется ПО ФАКТУ: значение — потолок, не резерв (0 Б до первого запроса).
# Rollback = убрать строку (снова 64 МиБ) + пересоздать контейнер.
shm_size: 1gb
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}