防止更新丢失

Objective

After completing this lesson, you will be able to 使用 Etags 防止数据丢失

并发控制

在下文中,我们希望获取 CAP 提供的选项的概览,以确保同时执行并发修改时的数据完整性。

CAP 运行时支持不同方法来避免以下视频中记录的更新不足情况。

乐观锁定

我们从基于 ETag(实体标签)的乐观锁定概念开始。要为模型实体启用 ETag,请将 @odata.etag 注释添加到实体定义的元素。

在所示示例中,托管方面的 modifiedAt 元素定义为 Books 实体和 Authors 实体的 ETag 元素。annotate 指令用于此目的,允许对现有定义进行注释。

注意

每次更新数据记录时内容唯一更改的元素适用于 ETag 元素。因此,预定义管理方面的 modifiedAt 元素是最佳选择。还可以使用每次更新时重新计算的更新计数器或 UUID。

ETag 的想法是识别实体的特定版本,在我们的示例中,是书或作者的版本。这可用于确保数据的完整性,如以下示例中所述,而不使用锁。

假设我们通过以下请求检索特定作者,因为我们希望更改其数据:

Code Snippet
1
GET Authors(18f76942-bfb3-40c5-8300-f999f14e9cc2)

通过此请求,作者版本(即 ETag 元素的值 modifiedAt)通过 ETag HTTP 响应标头自动返回,例如:

Code Snippet
1
ETag: W/"2024-03-15T11:30:48.069Z"

要回写作者上已更改的数据,请在相应变更请求的 If-Match HTTP 标头中按如下方式使用收到的 ETag 值:

Code Snippet
1234567
PUT Authors(18f76942-bfb3-40c5-8300-f999f14e9cc2) If-Match: W/"2024-03-15T11:30:48.069Z" Content-Type: application/json { ... }

然后 CAP 检查 modifiedAt 元素的内容是否同时更改。如果不是,则在数据库中更改作者数据,并更新 modifiedAt ETag 字段。如果是,则表示自读取数据后已通过其他请求更改作者。因此,CAP 会中止更改请求并为 HTTP 响应设置状态代码 412(前提条件失败)。响应正文包含类似于以下内容的错误:

JSON
12345
"error": { "code": "412", "message": "Precondition Failed", "@Common.numericSeverity": 4 }

悲观锁定

优化锁定可确保在通过不同请求进行并发修改时的数据完整性。

另一方面,悲观锁定可以确保在并发事务进行并发修改时数据的完整性。通过悲观锁定,您可以锁定数据,以便禁止其它事务以任何方式更改数据。

CAP 利用数据库锁进行悲观锁定,从而区分排它锁和共享锁。

独占锁定的数据记录不能由其他事务更改或读取。从数据库中读取数据记录时设置独占锁。CAP 的查询 API 为此目的提供了 forUpdate() 方法。

注意

稍后将讨论构建和执行查询。

共享锁还会阻止并行事务的并发更新。但是,它们允许所有事务读取锁定的数据记录。

为设置共享锁,查询 API 提供了 forShareLock() 方法。

获取锁(无论是独占锁还是共享锁)在当前事务完成时释放,即提交或回退。

注意

SQLite 不支持悲观锁定。

演示和练习:添加乐观并发控制

注意

在练习中,在 SAP Business Application Studio 中自行执行以下演示中的分步说明。

作为练习的起点,如果已成功完成,请使用上一练习实施输入验证的结果。或者,您还可以使用以下 GitHub 资源库中的分支 8_input_validation 作为起点:

https://github.com/SAP-samples/cap-development-learning-journey

可在 GitHub 资源库的 9_concurrency_control 分支中找到模拟的完整实施。

有关资源库内容及其使用方法的详细信息,可在此处找到。

观看视频,了解如何添加乐观并发控制。