Описание уровней изоляции
PostgreSQL имеет три уровня изоляции транзакций, которые препятствуют трем типам конфликтов параллелизма, грязных операций чтения, не повторяющихся операций чтения и фантомных операций чтения.
Типы конфликтов параллелизма
Чтение "грязных" данных
Чтение "грязных" данных происходит, когда одна транзакция считывает обновленную версию данных, которую редактирует другая транзакция. Однако это обновление никогда не фиксируется.
Например, транзакция возникает на сберегательной учетной записи, которая будет принимать баланс учетной записи до нуля. Перед фиксацией транзакции баланс учетной записи проверяется и транзакция откатывается, так как сберегательные счета не могут иметь баланс меньше нуля. В то же время запускается отчет для отображения текущего баланса всех сберегательных счетов. Если грязные считывания разрешены, то отрицательный баланс будет возвращен, даже если он никогда не фиксирует.
Неповторяемые операции чтения
Не повторяемое чтение происходит, если транзакция: считывает данные, другая транзакция обновляет данные, а начальная транзакция снова считывает данные и видит новые обновления.
Например, подключение A запускает транзакцию и считывает затраты на единицу и количество единиц для заказа, которые являются стоимостью 10 и число единиц 3. Затем подключение B запускает другую транзакцию и обновляет тот же порядок, чтобы задать затраты на единицу 12. В той же транзакции, что и исходный запрос, подключение A вычисляет общую стоимость заказа. Если не повторяемые операции чтения разрешены для подключения A, возвращает стоимость за единицу 10, количество единиц 3 и общая стоимость 36, что, очевидно, не имеет смысла.
Фантомные операции чтения
Фантомное чтение происходит, если транзакция: считывает данные, другая транзакция добавляет новую строку (или строки) к данным, а начальная транзакция снова считывает данные и видит новые обновления.
Например, подключение A запускает транзакцию и подсчитывает общее количество счетов за день в Париже. Количество счетов составило 1100 счетов для всех 10 магазинов в Париже. Затем подключение B запускает другую транзакцию и добавляет новый розничный магазин в Париже с 200 счетами за день открытия нового магазина. В транзакции Connection A система теперь подсчитывает количество магазинов для вычисления количества счетов на хранилище. Подключение A теперь разделит 1100 транзакций на 11 магазинов вместо исходного 10, которое существовало при выполнении запроса счетчика счетов. Это вычисление теперь возвращает неверное среднее значение 100, даже если в новом магазине было 200 счетов, за которые транзакция подключения A не учитывается в его среднем расчете.
Уровни изоляции
База данных Azure для PostgreSQL имеет три уровня изоляции транзакций: с зафиксированной операцией чтения, с повторяемой операцией чтения и сериализуемый уровень. Незафиксированная операция чтения недоступна в Базе данных Azure для PostgreSQL.
Как уровни изоляции влияют на конфликты параллелизма:
Уровень изоляции | «Грязное» чтение | Неповторяемые операции чтения | Фантомные операции чтения |
---|---|---|---|
Незафиксированные операции чтения* | Возможные способы | Возможные способы | Возможные способы |
Чтение подтверждено | Невозможно | Возможные способы | Возможные способы |
Уровень изоляции repeatable read | Невозможно | Невозможно | Возможные способы |
Упорядочиваемый уровень изоляции | Невозможно | Невозможно | Невозможно |
* Недоступно в PostgreSQL
Зафиксированные операции чтения являются уровнем изоляции по умолчанию в Базе данных Azure для PostgreSQL. Фиксация операции чтение оптимально подходит для большинства сценариев, так как она предотвращает чтение "грязных" данных, обеспечивая высокую производительность. Возможно наличие не повторяющихся операций чтения и фантомных операций чтения, но эти условия могут возникать только в том случае, если одновременно запрашивать одни и те же данные несколькими операторами SELECT.
Повторяемое чтение отличается от фиксации чтения, так как несколько инструкций SELECT в транзакции будут видеть одинаковые результаты, даже если другая транзакция обновила строки между выполнением двух инструкций SELECT транзакции. Если другая транзакция вставляет новые строки, эти строки не будут отображаться в результатах второй инструкции SELECT.
Сериализуемый уровень изоляции обеспечивает самый высокий уровень изоляции транзакций и работает так, как если бы разные транзакции выполнялись последовательно, то есть одна за другой. Недостаток уровня сериализации изоляции заключается в том, что если транзакция выполняет обновление, другие транзакции могут заблокировать его. Сериализуемая транзакция должна ждать завершения блокирующей транзакции, что влияет на производительность.
Сериализуемые транзакции также не могут вносить изменения в строки, изменяемые другими транзакциями во время сериализуемой транзакции. Если возникает конфликт, возвращается сообщение об ошибке, и поэтому важно, чтобы логика повторных попыток была встроена в приложения в случае, если используются сериализуемые транзакции.
Чтобы обновить уровни изоляции транзакций, используйте команду TRANSACTION ISOLATION LEVEL в транзакции.
Например:
BEGIN TRANSACTION
TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT * FROM humanresources.department
COMMIT;