【问题标题】:Are stored procedures in Cosmos DB automatically retried on conflict?Cosmos DB 中的存储过程是否会在发生冲突时自动重试?
【发布时间】:2020-08-13 07:18:39
【问题描述】:

Cosmos DB 中的存储过程是事务性的,并且在具有乐观并发控制的隔离 snapshop 下运行。这意味着可能会发生写入冲突,但会检测到它们以便回滚事务。

如果发生这种冲突,Cosmos DB 是自动重试存储过程,还是客户端收到异常(可能是 HTTP 412 前置条件失败?)需要自己实现重试逻辑?

【问题讨论】:

    标签: stored-procedures azure-cosmosdb


    【解决方案1】:

    我尝试并行运行 100 个存储过程实例,通过读取文档(不设置 _etag)会产生写冲突,等待一段时间然后在该文档中递增一个整数属性(再次不设置_etag)。

    到目前为止,在所有试验中,都没有发生错误,结果就像 100 次运行是按顺序运行的。所以初步的答案是:是的,Cosmos DB 会在写入冲突时自动重试运行 SP(或者可能通过锁定等其他方式强制执行事务隔离),因此客户端希望不必担心由于冲突而中止的 SP。

    很高兴听取 Cosmos DB 工程师的意见,这是如何实现的:重试、锁定还是其他方式?

    【讨论】:

    • 将我自己的答案标记为已接受,直到其他人发布更合格的答案。
    【解决方案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 失败与 Optimistic Concurrency 相关,在这些情况下,您正在控制您正在传递的 ETag。预计用户通过读取最新版本的文档来处理412,获取更新的ETag,并使用更新后的值重试操作。

      【讨论】:

      • 抱歉,这没有回答问题。我知道如何处理 412 失败,但问题是:假设您运行一个读取文档的存储过程,并在延迟后写入一个属性(没有 ETag),并且您有第二个同时运行的存储过程读取相同的文档并在延迟后写入另一个属性(没有 ETag)。发生什么了?两次运行的调度方式是两个过程都成功运行(但作为独立事务)还是其中一个失败?
      • 如果你对同一个文档进行并发写入,没有 Etag / Optimistic Concurrency,那么最后登陆的人就是定义文档内容的人,因为这些是完整的替换操作(没有部分更新支持)。他们不会失败。 412 仅在您使用 ETag 时才会发生。
      • 当然,但是如果在 SP 中读取或写入文档,服务器将隐式使用 ETag 或其他文档版本控制属性在后台执行 OCC。问题是冲突是否会导致 SP 中止、强制客户端处理故障(例如在具有快照隔离的 SQL Server 中),或者 Cosmos DB 是否透明地处理故障。到目前为止,我的实验表明后者。
      • 我没有发现任何迹象表明 Sproc 创建了隐式乐观并发。我进行了创建一个 Sproc 的测试,该 Sproc 对现有文档执行 upsert 并使用不同的值同时调用它。所有并发执行都成功,并且文档的内容是最新完成的执行。
      • 官方文档说 Cosmos DB Sprocs 在快照隔离下运行,这通常意味着某种形式的 OCC。不幸的是,没有记录精确的语义和保证。 :-(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多