Как стать автором
Обновить

Комментарии 12

Спасибо за статью, сохранил *thumbs up*

Рад, что понравилось.

Спасибо за статьи, довольно доступная подача не самого простого материала. Хорошо помогает упорядочить свои отрывочные знания.


Уточните, пожалуйста, следующий момент. Вот цитата: "Команда UPDATE сама выбирает минимальный подходящий режим блокировки; обычно строки блокируются в режиме FOR NO KEY UPDATE".
Плюс к этому известно, что любой апдейт в постгресе все равно действует как delete+insert, даже если обновляется одно "простое" поле. Во многих ORM удобно использовать save метод, который генерирует update на все поля, и изменившиеся, и нет. Постгрес достаточно умный, чтобы понять, что KEY поля не менялись, или нет? И вообще практика при апдейте указывать только нужные поля реально несёт какую-то пользу (ну кроме сокращения трафика).

Постгрес достатчно умный, чтобы понять, что KEY поля не менялись, или нет?

Достаточно (:


И вообще практика при апдейте указывать только нужные поля реально несёт какую-то пользу

Безусловно несет.
Если вы обновляете поля, которых нет ни в одном индексе, у вас работает HOT. Но если вы обновляете все поля (и у вас на таблице есть хотя бы один индекс) — увы.
Ну и журнальные записи будет меньше.

А HOT будет применен, если обновится поле с индексом, но значение останется тем же? По ссылке про него прочитал, но не совсем понятно, "обновление поля" — это любой апдейт или именно изменение значения.

Хм, век живи…
Я был уверен, что нет, но решил проверить. И оказалось, что если при обновлении значение фактически не меняется, то HOT работает. Более того, и в журнал ничего лишнего не пишется.
Так что обманул я вас, нет (почти) никакой разницы.

Спасибо. Явно указывать, что сохранять, все равно, конечно, надо, но в legacy коде хотя бы можно не рыться в надежде что-то таким образом оптимизировать :)

Егор, спасибо за статью. Есть небольшой вопрос. Изучаю материал вашей книжки. В ней есть такая фраза.

Обычно строка блокируется при изменении или удалении. В обоих случаях актуальная версия строки помечается как удаленная. Признаком служит номер транзакции в поле xmax, и этот же номер (в сочетании с дополнительными информационными битами) указывает на то, что строка заблокирована. Когда какая-либо транзакция собирается изменить строку, но видит в поле xmax актуальной версии номер незавершенной транзакции, она обязана дождаться ее завершения. После этого все блокировки будут сняты, и ожидающая транзакция сможет продолжить свою операцию над строкой.

Такое решение позволяет блокировать сколько угодно строк, не потребляя никаких ресурсов

Не совсем понимаю последнее предложение.

Простой пример.

Пусть у нас есть транзакция, которая обновляет, скажет, 100 000 строк в таблице. Пусть она еще не зафиксировалась.

Пусть есть вторая транзакция, которая пытается обновить все те же 100 000 строк. Означает ли это, что вторая транзакция создаст 100 000 tuple-блокировок? Если да, то все же "не потребляя никаких ресурсов" звучит не совсем правдиво.

Или же "не потребляя никаких ресурсов" относится к тому факту, что создание блокировок является своего рода отложенной операцией и при первом обновлении никакие блокировки фактически не создаются?

Тут смысл фразы в том, что постгрес не запоминает в памяти все 100 000 строк, которые заблокированы транзакцией. Память не расходуется. Иначе большие (по количеству изменённых строк) транзакции будут очень сильно потреблять память.

Вторая транзакция поставит блокировку на номер первой транзакции, то есть будет ждать её завершения. И это все затраты по памяти, которые тут возникнут.

Все так.

Спасибо.

Странно, видимо у меня есть недопонимание. Как будто статья говорит об обратном - что будет захвачена и tuple блокировка и блокировка номера транзакции.

Вот ключевой фрагмент:

Если нам надо дождаться освобождения строки, фактически мы должны дождаться окончания блокирующей транзакции — все блокировки снимаются при фиксации или откате. А для этого можно запросить блокировку номера блокирующей транзакции (которая, напомню, удерживается самой транзакцией в исключительном режиме). Таким образом число используемых блокировок пропорционально числу одновременно работающих процессов, а не количеству изменяемых строк.

После того как вторая транзакция "упрется" в первую заблокированную строку, она уже не продвинется дальше, пока блокировка номера первой транзакции не будет снята.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий