Pull to refresh

Comments 13

Фактически блокируется только повторное изменение одной и той же строки.

Я бы все же уточнил, что блокируется так же добавление совпадающего листа уникального индекса или exclude constraint. То есть если одна транзакция создала или модифицировала запись со значением уникального индекса X, то параллельная ей транзакция, пытающаяся создать или модифицировать запись с таким же значением уникального индекса будет заблокирована. Если первая транзакция выполнит rollback, то вторая продолжит работу. Если commit - то вторая аварийно завершиться по дублированию уникального индекса.

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

Верно подмечено, исправил в тексте.

UNIQUE и EXCLUDE вызывают блокировки при проверке ограничений.

Также, если одна транзакция удаляет или изменяет запись, на которую ссылается другая запись через внешний ключ, другая транзакция, которая пытается создать или изменить запись, ссылающуюся на удаляемую или изменяемую запись, может быть заблокирована. Вторая транзакция должна ждать, пока первая транзакция завершится, чтобы проверить, остается ли ссылка валидной.

Блокировки строк ещё имеют разные режимы — ссылка на документацию.

Очень много разных нюансов, которые не получается рассмотреть сразу. Может, когда-нибудь будет статья на эту тему.

Полезно, спасибо. Помню однажды был крайне удивлен почему PostgreSQL не блокировал мой код, который использовал Serializable. Потом почитал про версионирование и прозрел.

Годами был уверен, что в pg по умолчанию READ UNCOMMITTED , настало время преисполниться и почитать документацию.

Был какой-то старый кейс в памяти, когда было грязное чтение, но теперь уже даже не могу вспомнить, что это был за кейс и что именно там происходило.

Спасибо за статью =)

Когда-то читал, что в PostgreSQL менялась модель реализации транзакционности, на снимки вроде перешли в 9-й версии, если мне не изменяет память. Вполне возможно, что до этого уровни изоляции read uncommitted и read committed там отличались тогда и по умолчанию стоял как раз read uncommitted. Ну а сейчас, поскольку эти два уровня ничем не отличаются, можно спокойно говорить, что теперешнее умолчание — read uncommitted :)

PostgreSQL всегда использовал модель многоверсионности (MVCCMulti-Version Concurrency Control) для управления конкурентностью транзакций. Эта модель основана на использовании снимков данных (snapshot isolation) и была реализована с самого начала. Документация PostgreSQL 7.1.

Уровень изоляции по умолчанию тоже всегда был Read Committed: документация PostgreSQL 7.1.

Хотел отдельным комментарием про это написать, да) При переходе с MS SQL наличие MVCC стало сюрпризом)

Спасибо, за великолепные диаграммы. Из всех гайдов по уровням изоляции еще не видел ни одного настолько наглядного и доступного.

Диаграмма на 2.13 неудачная. Где же тут фантомное чтение? Читались данные всего один раз и результат выполнения обеих транзакций, работающих параллельно, в точности идентичен результату, как если бы они выполнялись последовательно: сначала транзакция 1, а потом транзакция 2. Результат получился правильный.

Я немного запутал тем, что сначала начинается транзакция 2, а потом транзакция 1 (в тексте ниже это написано). Исправлю на картинке на транзакции 3 и 4 (чтобы нумерация была по порядку, как и на самом деле в Postgres).

А "фантомное чтение" тут имеется. Дело в том, что Repeatable Read предотвращает неповторяющиеся чтения для существующих строк, но НЕ для новых строк, которые могут быть добавлены другой транзакцией и удовлетворять условиям запроса. Что как раз изображено на рис. 2.13.

С точки зрения бизнес-логики это правильно, но не с точки зрения изоляции транзакций.

Я ожидал этого комментария. Да, с точки зрения формальной логики вы, может быть, и правы, только вот это всё равно ничего не проясняет. Я потому и написал, что пример всего лишь «неудачный», а не «неправильный». Потому что на самом деле он не демонстрирует проблему, в результате новичок только запутается ещё больше.

Почему «может быть» в формулировке выше: у вас всего одно чтение. Из документации к PostgreSQL (выделение моё):

фантомное чтение

Транзакция повторно выполняет запрос, возвращающий набор строк для некоторого условия, и обнаруживает, что набор строк, удовлетворяющих условию, изменился из-за транзакции, завершившейся за это время.

В примере нет никаких повторных чтений тех же самых строк с отличающимся результатом — признак аномалии фантомного чтения. Значит, и аномалии нет.

Исправил рисунок 2.13

Спасибо. Полезно иногда вспоминать базу.

Sign up to leave a comment.

Articles