большая 10Тб где-то.
Хотелось добавить бы (нуллабл и нет) колонку, но на таблицу берется write lock (пробовал на стейдже - все записи остановились и какбы нехорошо, сервисы попадают держать все в памяти).
Я так прикидываю ALTER ADD COLUMN займет 20 мин что много, есть варианты как это решить?
Из самого адекватного пришло такое: создать новую пустую партицированную таблицу с желаемыми колонками, и каждую партицию отцепить, добавить колонки и подцепить к новой. Муторно, но вроде заработает.
Есть варианты проще?
Вообще, если не указывать параметр default value, то добавление колонки происходит очень быстро.
всегда жил с такой мыслью, пока не сделал: ATLER TABLE foo ADD COLUMN bar DECIMAL; и не увидел падение записей по всем сервисам UPD: не это прикол какой-то, я только что повторил этот запрос (отмененный ранее) и оно отработало за полсекунды, втф
хм, ПГ пересчитал какие-то статистики или что? я не троль: cryptowatch=> ALTER TABLE foo ADD COLUMN temp_test_column DECIMAL; ^CCancel request sent ERROR: canceling statement due to user request Time: 132392.104 ms (02:12.392) cryptowatch=> ALTER TABLE foo ADD COLUMN temp_test_column DECIMAL; ALTER TABLE Time: 663.706 ms cryptowatch=>
Ему нужна эксклюзивная(?) блокировка на таблицу и оно будет ждать окончания всех пишущих транзакций. На это время действительно всё остановится. Автовакуум очень сильно умеет в длинные блокировки. Надо успеть «проскочить» с DDL. Есть даже набор крутилок для этого, но я по памяти не помню и не готов их искать.
хм, то есть это неболее чем мое невезение? попать на блок в 2 минуты, а буквально на следующий раз в полсекунды? прикольно. осталось понять что мне ждать на проде, в цикле пробовать АЛЬТЕР и если не прошел за 10сек - отменять и повторять?)
Ну, я не большой специалист, но общая канва такая :)
ок, походу я попробую еще подобавлять больше колонок в таблицу и посмореть поведение, спасибо что стейдж и прод 1к1 по объему. спасибо)
насколько я понял, общая практика примерно такая: поставить statement_timeout в < 1 секунды и пытаться добавить колонку в цикле, пока не получится, на всякий случай с ограничением скажем в 1000 попыток.
угу, походу, я такое встречал, но думал это больше паранойя, а вот оно как..спасибо за подсказку)
На самом деле дажэ с константным default value оно отработает такжэ быстро (ну, дождётся завершэния всех предыдущих транзакцый, которые использовали эту таблицу, чтобы получить свой лок).
ага, с 11 или 13й должно быть ок уже, но все равно не мой кейз) мне без дефолта пока добавить надо
Вообще -- можно заранее посмотреть в pg_stat_activity, как там сейчас с блокировками этой таблицы. Ну и да, общая идея -- такая. Можно дажэ пару секунд таймаута, а не 10 -- если каталог в памяти (а на активно используемой базе он в памяти) -- то пройдёт и быстрее, чем за пару секунд.
она постоянно юзается, может где-то рано утром там мало транзакций еще будет, но не уверен что это сильно поможет, ретрай кажется более чотким решением
pg_locks, кстати, а не pg_stat_activity. И да, смотреть -- кто держыт локи на эту таблицу и сколько он ужэ это делает. Если полчаса кто-то держыт, то, скорее всего, быстро не отдаст. Если миллисекунды -- то наоборот.
там все краткосрочное, только 1 писатель (ну 1 сервис) и там коротенькие COPY и ничего другого
Значит, должно за секунду отработать. А где 10 секунд -- смотрите pg_stat_activity и pg_locks, на ком оно там висит.
буду мониторить, есть уже 1 подозреваемый после пары минут размышлений, спасибо)
А, кстати "1 писатель" -- в смысле все остальные читатели? Это тожэ важно, блокировка эксклюзивная и требует закончить всех читателей тожэ.
хм, мне казалось только write лочится, риды могут дальше работать (и метрики это подтверждали, только записи зависли) я все больше склоняюсь, что это был вакуум
да, проверили, BEGIN READ ONLY; и в другой сессии ALTER TABLE и все виснет, для меня это новость ,я на такое не напарывался (хотя в таком поведении есть смысл) чувствую дикий стыд за себя
Обсуждают сегодня