Уровни изоляции транзакций PostgreSQL

Уровни изоляции транзакций являются ключевым аспектом реляционных баз данных, включая PostgreSQL. Они определяют, как данные изолируются друг от друга при выполнении параллельных транзакций, обеспечивая согласованность и целостность данных. PostgreSQL поддерживает стандартные уровни изоляции, определенные ANSI SQL, а также дополнительные режимы, обеспечивая гибкость и оптимизацию работы с данными. Уровни называются во взаимосвязи с аномалиями, которые допускаются или нет на том или другом уровне изоляции:

Уровни изоляции и их особенности:

  • READ UNCOMMITTED (Чтение неподтвержденных данных): Наименьший уровень изоляции, где транзакции видят неподтвержденные изменения других транзакций. Этот уровень обеспечивает максимальную параллельность, но может привести к непредсказуемым результатам из-за “грязного чтения”.
  • READ COMMITTED (Чтение подтвержденных данных): Большинство баз данных, включая PostgreSQL, используют этот уровень по умолчанию. Транзакции видят только подтвержденные изменения других транзакций. Это предотвращает “грязное чтение”, но допускает “неповторяющееся чтение”.
  • REPEATABLE READ (Повторяемое чтение): В этом режиме транзакции видят только данные, которые были считаны на момент начала транзакции. Это предотвращает “грязное чтение” и “неповторяющееся чтение”, но может привести к “фантомным” записям, когда другая транзакция вставляет новые записи.
  • SERIALIZABLE (Сериализуемость): Самый строгий уровень изоляции. Транзакции выполняются так, как если бы они выполнялись последовательно. Это предотвращает “грязное чтение”, “неповторяющееся чтение” и “фантомные” записи. Однако это может привести к блокировкам и ухудшению производительности.

Выбор уровня изоляции:

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

Изменение уровня изоляции в PostgreSQL:

Вы можете изменить уровень изоляции для текущей транзакции с помощью команды SET TRANSACTION ISOLATION LEVEL.

Второй вариант – сразу начать транзакцию на нужном уровне изоляции, например:

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;

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

Посмотрим на практике:

Подключимся одновременно с двух сеансов к одному инстансу PostgreSQL и в первой сессии выполним команды:

CREATE TABLE test (i serial, amount int);
INSERT INTO test(amount) VALUES (1);
INSERT INTO test(amount) VALUES (2);
show transaction isolation level;

CREATE TABLE
postgres=# INSERT INTO test(amount) VALUES (1);
INSERT 0 1
postgres=# INSERT INTO test(amount) VALUES (2);
INSERT 0 1
postgres=# show transaction isolation level;

transaction_isolation

read committed
(1 row)

И начнем транзакцию на стандартном уровне изоляции PostgreSQL – READ COMMITTED:


BEGIN;
SELECT * FROM test;

i | amount
—+——–
1 | 1
2 | 2
(2 rows)

Выполним команды из 2 консоли:
BEGIN;
UPDATE test set amount = 3 WHERE i = 1;
COMMIT;

Проверим еще раз состояние в первой консоли:
SELECT * FROM test;
COMMIT;

i | amount
—+——–
2 | 2
1 | 3
(2 rows)

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

Теперь посмотрим как себя поведет PostgreSQL на уровне изоляции REPEATABLE READ:

В 1 консоли выполним:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM test;

BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
SELECT * FROM test;
i | amount
—+——–
2 | 2
1 | 3
(2 rows)

Во второй консоли:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
INSERT INTO test VALUES (8);
COMMIT;

И прочитаем еще раз данные из первой консоли:
SELECT * FROM test;

i | amount
—+——–
2 | 2
1 | 3
(2 rows)

Видим, что аномалии “фантомное чтение” мы не наблюдаем.

Итоги:

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

Более подробно про Уровни изоляций в моём видео на ютуб.

Больше про транзакции в моей статье

Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

один × три =