单个记录的 DynamoDB ACID 事务

Posted

技术标签:

【中文标题】单个记录的 DynamoDB ACID 事务【英文标题】:DynamoDB ACID transaction for single record 【发布时间】:2022-01-18 06:12:17 【问题描述】:

我有一个 DynamoDB“My_Table”,索引在“lock_status”上:

  
   my_pk: string,
   lock_status: string,
   useful_data: string,
 

两个不同的线程可以在同一条记录上执行下面的更新代码吗?

本质上,我希望只有一个线程可以访问任何给定记录的“有用数据”。为此,我在线程处理此项目时通过 lockStatus “锁定”记录。我担心的是两个线程同时执行这段代码。他们都根据“ConditionExpression”找到相同的记录并锁定相同的记录。

const client = new AWS.DynamoDB.DocumentClient();
return await client.update(
        TableName: 'My_Table',
        Limit: 1,
        UpdateExpression: 'set lockStatus = :status_locked', 
        ConditionExpression: 'lockStatus <> :status_available',
        ExpressionAttributeValues: 
            ':status_locked': 'LOCKED',
            ':status_available': 'AVAILABLE',
        ,
        ReturnValues: 'ALL_NEW',
    ).promise();

如果我使用 TransactWriteItem,这似乎可以避免这个问题,但是我可以在我的简单场景中使用简单更新吗?

【问题讨论】:

【参考方案1】:

您可以为此使用乐观锁定 - 这个想法相当简单。 您为您的项目创建一个版本属性,该属性是一个将递增的整数。


  pk: 123
  sk: 123
  version: 0
  randomValue: abc

当您阅读该项目以对其进行更新时,您会记下当前版本号。更新项目后,您还会增加版本号。因此,如果您想更新随机值,您将写入 DynamoDB 的项目将如下所示:


  pk: 123
  sk: 123
  version: 1
  randomValue: newValue

您现在向 update 或 putitem 调用添加条件表达式,以确保仅当该项目的当前版本仍为 0 时才成功。

这样调用将失败,如果在您处理项目时其他人更新了该项目并且您可以再次读取它,更新它并再次写入。 如果调用成功,你就知道没有其他人弄乱了这个项目。

如果您对此感到好奇,我还写了一篇更详细的博文:link

【讨论】:

以上是关于单个记录的 DynamoDB ACID 事务的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL中的ACID特性介绍

分布式事务解决方案

事务是什么?事务的4个特点(ACID),事务的开启与结束

数据库管理(事务ACID并发封锁可串行化隔离)(转)

事务的ACID属性&&五种状态

[MySQL]事务ACID详解