首页 > 解决方案 > 并行 API 调用读取一行并根据获取的结果更新它,在 mysql 中,导致竞争条件

问题描述

在播放框架上用 scala编写的应用程序。

MySql表: 表example_table如下:

CREATE TABLE example_table
(
  `itemSetId`    BIGINT NOT NULL,
  `version`      BIGINT(20) NOT NULL,
  `status`       VARCHAR(20) NULL,
  `activatedAt`  BIGINT NULL,
  `typeA_id` varchar(36) NULL,
  `typeB_id` varchar(36) NULL,
  PRIMARY KEY (`itemsetId`, `version`)
);

这里状态可以是活动的或非活动的,typeA_idtypeB_id是 UUID 字符串,版本是时间戳。

对于状态= 活动的特定itemsetId ,表中一次应该只有一行。

API 的工作:这两个 API 都对 itemsetID 做了类似的事情,比如 123,除了 API-1 更新typeA_id而 API-2 更新typeB_id

  1. 从 itemsetId=123 和 status=active 的表中读取最新版本(时间戳)的行。
  2. 做一些服务级别逻辑,并生成一个新的 UUID。
  3. 将在步骤 1 中获取的行的状态设置为inactive,在表中创建一个新行(类似于在步骤 1 中获取的行),除了status = active并且这里的 API 将在步骤 1 中获取的行更新为typeA_id =newUUID,而其他 API 更新typeB_id =newUUID。

对于状态= 活动的特定itemsetId ,表中一次应该只有一行。

当两个 API 被同时调用时,就会发生争用情况。这两个 API 都读取给定 itemsetId 的最新行,并且状态=active。两者都有一些服务级别逻辑。但是其中一个 API 更新typeA_id并创建一个状态= 活动的新行,而另一个 API 更新typeB_id并创建另一个状态= 活动的新行。因此,我们有两行status = active,当我们打算让最后一行status = active 并且 typeA_id 和 typeB_id 中的每一个都在同一行中更新时。虽然我们不关心在这两者之间创建了多少行,但最终我们打算在一行中同时进行这两种更改。

实际发生了什么:

要么,两个 API 同时达到上述步骤 3,因此创建了两行,对 typeA_id 和 typeB_id 的更新在单独的行中。

或者,其中一个 API 完成第 3 步并创建一个新行,状态=active 和 typeA_id 更新,然后另一个 API 到达第 3 步,停用所有 status=active 的行(包括由 API-1 创建的行) 并创建一个仅更新 typeB_id 的新行。

我无法提出具体的解决方案,请帮助。

标签: mysql

解决方案


推荐阅读