Автоматически ли повторяются хранимые процедуры в Cosmos DB при конфликте?

#stored-procedures #azure-cosmosdb

#хранимые процедуры #azure-cosmosdb

Вопрос:

Хранимые процедуры в Cosmos DB являются транзакционными и выполняются в isolation snapshop с оптимистичным управлением параллелизмом. Это означает, что конфликты записи могут возникать, но они обнаруживаются, поэтому транзакция откатывается.

Если возникает такой конфликт, Cosmos DB автоматически повторяет хранимую процедуру или клиент получает исключение (возможно, сбой предварительного условия HTTP 412?) и ему необходимо реализовать саму логику повторных попыток?

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

1. Вы когда-нибудь находили что-нибудь конкретное по этому поводу? Мне было интересно, следует ли мне настраивать etag при обновлении документа в моем sproc.

Ответ №1:

Я попытался запустить 100 экземпляров хранимых процедур параллельно, что привело бы к конфликту записи, прочитав документ (без настройки _etag ), подождав некоторое время, а затем увеличив свойство integer в этом документе (снова без настройки _etag ).

Во всех пробных версиях до сих пор ошибок не возникало, и результат был таким, как если бы 100 запусков выполнялись последовательно. Итак, предварительный ответ таков: да, Cosmos DB автоматически повторяет запуск SP при конфликтах записи (или, возможно, обеспечивает изоляцию транзакций каким-либо другим способом, таким как блокировка), поэтому клиентам, надеюсь, не нужно беспокоиться об прерванных SP из-за конфликтов.

Было бы здорово услышать от инженера Cosmos DB, как это достигается: повторная попытка, блокировка или что-то другое?

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

1. Пометил мой собственный ответ как принятый, пока кто-нибудь другой не опубликует более квалифицированный ответ.

Ответ №2:

Вы правы в том, что это нигде должным образом не задокументировано. Вот как можно выполнить проверку OCC в хранимой процедуре:

 function storedProcedureWithEtag(newItem)
{
    var context = getContext();
    var collection = context.getCollection();
    var response = context.getResponse();

    if (!newItem) {
        throw 'Missing item';
    }

    // update the item to set changed time
    newItem.ChangedTime = (new Date()).toISOString();
    var etagForOcc = newItem._etag;

    var upsertAccecpted = collection.upsertDocument(
        collection.getSelfLink(),
        newItem,
        { etag: etagForOcc },       // <-- Pass in the etag
        function (err2, feed2, options2) {
            if (err2) throw err2;

            response.setBody(newItem);
        }
    );

    if (!upsertAccecpted) {
        throw "Unable to upsert item. Id: "   newItem.id;
    }
}
  

Оценка: https://peter.intheazuresky.com/2016/12/22/documentdb-optimistic-concurrency-in-a-stored-procedure/

Ответ №3:

SDK не повторяет попытку при 412, сбои 412 связаны с оптимистичным параллелизмом, и в этих случаях вы контролируете передаваемый ETag. Ожидается, что пользователь обработает 412, прочитав последнюю версию документа, получит более новый ETag и повторит операцию с обновленным значением.

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

1. Извините, это не отвечает на вопрос. Я знаю, как обработать 412 сбоев, но вопрос в следующем: предположим, вы запускаете хранимую процедуру, которая считывает документ и после задержки записывает свойство (без ETag), и у вас есть вторая хранимая процедура, которая выполняется одновременно, которая считывает тот же документ и после задержки записывает другое свойство (без ETag). Что происходит? Запланированы ли два запуска таким образом, чтобы обе процедуры выполнялись успешно (но как изолированные транзакции) или одна из них завершается сбоем?

2. Если вы выполняете одновременную запись в один и тот же документ без Etag / оптимистичного параллелизма, то тот, кто завершает работу последним, определяет содержимое документа, потому что это операции полной замены (поддержка частичного обновления отсутствует). Они не завершаются сбоем. 412 происходит только в том случае, если вы используете ETag.

3. Конечно, но если документ считывается или записывается в SP, сервер неявно использует ETag или какое-либо другое свойство управления версиями документа для выполнения OCC под капотом. Вопрос заключался в том, приводит ли конфликт к прерыванию SP, заставляя клиента иметь дело с ошибкой (как в SQL Server с изоляцией моментальных снимков), или Cosmos DB обрабатывает сбой прозрачно. Мои эксперименты пока предполагают последнее.

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

5. В официальном документе говорится, что Sprocs Cosmos DB выполняются в изоляции от моментальных снимков, что обычно подразумевает некоторую форму OCC. К сожалению, точная семантика и гарантии не документированы. 🙁