Поделиться через


Управление транзакциями и оптимистическое управление параллелизмом

ОБЛАСТЬ ПРИМЕНЕНИЯ: NoSQL

Транзакции базы данных обеспечивают безопасную и предсказуемую модель программирования для работы с одновременными изменениями данных. Традиционные реляционные базы данных, такие как SQL Server, позволяют писать бизнес-логику с помощью хранимых процедур и триггеров, а затем отправлять их на сервер для выполнения непосредственно в ядре СУБД.

С традиционными реляционными базами данных необходимо иметь дело с двумя разными языками программирования: нетрансляционным языком программирования приложений, таким как JavaScript, Python, C# или Java; и язык программирования транзакций, например T-SQL, который изначально выполняется базой данных.

Ядро СУБД в Azure Cosmos DB поддерживает транзакции с полным соблюдением ACID (атомарность, согласованность, изоляция, долговечность) с изоляцией моментальных снимков. Все операции базы данных в области логической секции контейнера выполняются транзакционно в ядре СУБД, размещенном репликой секции. К ним относятся операции записи (обновление одного или нескольких элементов в логическом разделе) и операции чтения.

В следующей таблице перечислены различные операции и типы транзакций:

Операция Тип операции Транзакция с одним или несколькими элементами
INSERT (без предшествующего и последующего триггера) Написать Транзакция для одного элемента
INSERT (с предшествующим или последующим триггером) Запись и чтение Транзакция с несколькими элементами
Заменить (без предшествующего и последующего триггера) Написать Транзакция для одного элемента
REPLACE (с предшествующим или последующим триггером) Запись и чтение Транзакция с несколькими элементами
UPSERT (без предшествующего и последующего триггера) Написать Транзакция для одного элемента
UPSERT (с предшествующим или последующим триггером) Запись и чтение Транзакция с несколькими элементами
DELETE (без предшествующего и последующего триггера) Написать Транзакция для одного элемента
DELETE (с предшествующим или последующим триггером) Запись и чтение Транзакция с несколькими элементами
Выполнение хранимой процедуры Чтение и запись Транзакция с несколькими элементами
Выполнение процедуры слияния, инициируемое системой Написать Транзакция с несколькими элементами
Система инициировала выполнение удаления элементов, срок жизни (TTL) которых истек. Написать Транзакция с несколькими элементами
Читать Читать Операция по одному элементу
Лента изменений Читать Транзакция с несколькими элементами
Чтение с разбивкой на страницы Читать Транзакция с несколькими элементами
Постраничный запрос Читать Транзакция с несколькими элементами
Выполнение определяемой пользователем функции в составе запроса с разбивкой на страницы Читать Транзакция с несколькими элементами

Транзакции с несколькими элементами

Azure Cosmos DB позволяет создавать хранимые процедуры, триггеры и определяемые пользователем процедуры и процедуры слияния в JavaScript. Ядро СУБД Azure Cosmos DB имеет встроенную поддержку выполнения JavaScript. Вы можете зарегистрировать хранимые процедуры, предварительные/последующие триггеры, пользовательские функции (UDF) и процедуры слияния в контейнере, а затем выполнять их транзакционно в ядре СУБД Azure Cosmos DB. Создание логики приложения на JavaScript допускает естественное выражение потока управления, области видимости переменных, присвоения, а также интеграцию примитивов обработки исключений с транзакциями базы данных непосредственно на JavaScript.

Хранимые процедуры, триггеры, определяемые пользователем функции и процедуры слияния на базе JavaScript помещаются в окружающую транзакцию ACID с изоляцией моментального снимка для всех элементов в логическом разделе. Если программа JavaScript вызывает исключение, вся транзакция прерывается и откатывается. Полученная модель программирования является простой, но эффективной. Разработчики JavaScript получают надежную модель программирования, сохраняя привычные языковые конструкции и библиотечные примитивы.

Возможность выполнить код JavaScript непосредственно в ядре СУБД повышает производительность операций над элементами контейнера в базе данных и обеспечивает поддержку транзакций. Кроме того, так как ядро СУБД Azure Cosmos DB изначально поддерживает JSON и JavaScript, несоответствие между системами типов приложения и базой данных отсутствует.

Управление оптимистичным параллелизмом

Элемент управления оптимистичным параллелизмом (OCC) позволяет предотвратить потерянные обновления и удаления. Для конфликтующих одновременных операций применяется обычная пессимистическая блокировка ядра СУБД, размещенного в том же логическом разделе, что и обрабатываемый элемент. Когда две параллельные операции пытаются обновить последнюю версию элемента в логическом разделе, одна из них выигрывает, а другая завершается ошибкой. Однако если одна или две операции, пытающиеся одновременно обновить один и тот же элемент, ранее считывали старое значение элемента, база данных не знает, является ли ранее прочитанное значение либо обоими конфликтующими операциями действительно последним значением элемента.

К счастью, эта ситуация может быть обнаружена с помощью OCC, прежде чем разрешить двум операциям вводить границу транзакции внутри ядра СУБД. OCC защищает данные от случайного перезаписи изменений, внесенных другими пользователями. Она также не позволит другим процессам случайно перезаписать ваши собственные изменения.

Реализация управления оптимистичной конкурентностью с помощью заголовков ETag и HTTP

Каждый элемент, хранящийся в контейнере Azure Cosmos DB, имеет системное свойство _etag . Значение _etag создается и обновляется на сервере автоматически при каждом обновлении элемента. Вы можете использовать _etag вместе с предоставленным клиентом заголовком if-match запроса, чтобы сервер мог решить, можно ли условно обновить элемент. Если значение заголовка if-match совпадает со значением _etag на сервере, элемент затем обновляется. Если значение в заголовке запроса if-match потеряло актуальность, сервер отклоняет операцию и выводит ответное сообщение "HTTP 412: необходимое условие не выполнено". Затем клиент может заново запросить элемент, чтобы получить его текущую версию на сервере, или заменить версию элемента на сервере своим собственным значением _etag для этого элемента. Кроме того, _etag в сочетании с заголовком if-none-match позволяет определить, требуется ли повторное извлечение ресурса.

Значение _etag изменяется для элемента при каждом его обновлении. В операциях замены элемента значение if-match следует явным образом включить в параметры запроса. Для примера см. образец кода на GitHub. Значения _etag неявно проверяются для всех записанных элементов, затронутых хранимой процедурой. Если обнаружен конфликт, хранимая процедура откатывает транзакцию и создает исключение. Такой метод гарантирует, что операции записи хранимой процедуры применяются атомарным образом, то есть "все или ничего". Приложение получает сигнал о необходимости повторно применить обновления и повторить исходный запрос клиента.

Оптимистическое управление параллелизмом и распределение глобальных данных

Одновременные обновления элемента подвергаются ОСС с помощью протокольного уровня связи Azure Cosmos DB. Для учетных записей Azure Cosmos DB, настроенных для записи в одном регионе, Azure Cosmos DB гарантирует, что клиентская версия элемента, который вы обновляете (или удаляете), совпадает с версией элемента в контейнере Azure Cosmos DB. Это обеспечивает защиту ваших записей от случайного изменения записями других, и наоборот. В многопользовательской среде элемент управления оптимистическим параллелизмом защищает вас от случайного удаления или обновления неправильной версии элемента. Это обеспечивает защиту от печально известных проблем "потерянного обновления" и "потерянного удаления".

В учетной записи Azure Cosmos DB, настроенной для многорегиональной записи, данные могут быть независимо зафиксированы во вторичных регионах, если их _etag соответствует данным в локальном регионе. После локального фиксирования новых данных в дополнительном регионе они затем объединяются в концентраторе или основном регионе. Если политика разрешения конфликтов объединяет новые данные в узловой регион, эти данные затем глобально реплицируются с новым _etag. Если политика разрешения конфликтов отклоняет новые данные, дополнительный регион возвращается к исходным данным и _etag.

Следующие шаги

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