From 9f179836899a0bde97983793cf214f712bc5d8ee Mon Sep 17 00:00:00 2001 From: bot-backend Date: Wed, 19 Aug 2026 15:02:23 +0500 Subject: [PATCH] =?UTF-8?q?fix(tradein):=20=D0=BC=D0=B8=D0=B3=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20267=20=E2=80=94=20lock=5Ftimeout,=20=D0=BA?= =?UTF-8?q?=D0=B0=D0=BA=20=D1=82=D1=80=D0=B5=D0=B1=D1=83=D0=B5=D1=82=20?= =?UTF-8?q?=D0=B3=D0=B5=D0=B9=D1=82=20#2752?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Гейт `check-migration-lock-timeout.py` в ci.yml поймал правильно: `ADD COLUMN` без `SET LOCAL lock_timeout` — блокирующий DDL. Мой комментарий в первой версии был вдобавок обманчив: «блокировки не берёт, ADD COLUMN без DEFAULT не переписывает таблицу». Переписывания действительно нет, но ACCESS EXCLUSIVE берётся, и опасно не удержание лока, а ОЖИДАНИЕ его выдачи — ждущий DDL встаёт в очередь перед новыми запросами приложения к той же таблице. Так миграция 250 простояла 29 минут за чужой psql-сессией. Переписал комментарий под то, что происходит на самом деле. Refs #2899, #2752 --- ...7_trade_in_estimates_market_percentile.sql | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tradein-mvp/backend/data/sql/267_trade_in_estimates_market_percentile.sql b/tradein-mvp/backend/data/sql/267_trade_in_estimates_market_percentile.sql index 90be92ad..55b4a487 100644 --- a/tradein-mvp/backend/data/sql/267_trade_in_estimates_market_percentile.sql +++ b/tradein-mvp/backend/data/sql/267_trade_in_estimates_market_percentile.sql @@ -6,15 +6,25 @@ -- позицию по сохранённому top-10 нельзя — это другая популяция, поэтому значение -- обязано персиститься вместе с оценкой. -- --- smallint: диапазон значений 1..99 по построению (`_market_percentile` зажимает --- края — «0-й перцентиль» читался бы как «дешевле всех на свете», хотя означает лишь --- край выборки). NULL = когорта меньше MARKET_PERCENTILE_MIN_N (15) либо оценки нет. +-- smallint: диапазон 1..99 по построению (`_market_percentile` зажимает края — +-- «0-й перцентиль» читался бы как «дешевле всех на свете», хотя означает лишь край +-- выборки). NULL = когорта меньше MARKET_PERCENTILE_MIN_N (15) либо оценки нет. +-- Бэкфилла нет и быть не может: позицию старых строк восстановить не из чего. -- --- Идемпотентно: IF NOT EXISTS. Блокировки не берёт (ADD COLUMN без DEFAULT в PG 11+ --- не переписывает таблицу). +-- ПРО ЛОКИ (#2752). ADD COLUMN без DEFAULT в PG 11+ не переписывает таблицу и держит +-- ACCESS EXCLUSIVE миллисекунды — но ЖДАТЬ его выдачи может сколько угодно, и всё это +-- время ждущий DDL стоит в очереди ПЕРЕД новыми запросами приложения к той же таблице. +-- Ровно так миграция 250 встала на 29 минут за чужой psql-сессией. lock_timeout +-- ограничивает только ожидание: не дождались — красный деплой вместо тихой очереди. +BEGIN; + +SET LOCAL lock_timeout = '5s'; + ALTER TABLE trade_in_estimates ADD COLUMN IF NOT EXISTS market_percentile smallint; COMMENT ON COLUMN trade_in_estimates.market_percentile IS '#2899: доля аналогов дешевле этой квартиры, 1..99. NULL — когорта < 15 лотов. ' 'НЕ location_index_pct (тот про район против медианы города).'; + +COMMIT;