我有一个自定义实体,它几乎具有实时更新(大约每分钟更新1000次)。由于相同的实体记录可以在不同的批处理更新请求中得到更新,并且请求来自不同的异步源,因此CDS中较新的更新可能会被稍旧的更新覆盖。
由于网络延迟或其他原因,S1服务稍慢,服务S2启动了对实体记录A的更新调用,并在8.03 PM上进行了数据处理
服务-1现在在同一实体记录上触发更新-1,而发生在8.03PM的更新会被在8.02PM发生的更新覆盖,导致数据丢失。
我已经在第10阶段(预验证)为我的自定义实体的Update消息注册了一个插件。此插件将输入参数中的datamodifiedon属性与来自插件上下文的预实体图像中的属性进行比较。并抛出无效的插件执行异常,如果预实体映像已经具有更多最新的datamodifiedon属性。
// If ModifiedOn value in pre-image is later than the one received in input parameters, this is an obsolete request and must be rejected.
if (preImage.Contains("datamodifiedon")
&& preImage.GetAttributeValue<DateTime>("datamodifiedon") != DateTime.MinValue
&& entity.Contains("datamodifiedon")
&& entity.GetAttributeValue<DateTime>("datamodifiedon") != DateTime.MinValue
)
{
if (DateTime.Compare(preImage.GetAttributeValue<DateTime>("datamodifiedon"), entity.GetAttributeValue<DateTime>("datamodifiedon")) > 0)
{
string traceMessage = "PreOperationLiveWorkItemUpdatePlugin: Update request is obsolete. datamodifiedon field found in pre-entity image: "
+ preImage.GetAttributeValue<DateTime>("datamodifiedon")
+ "datamodifiedon field in Input parameters: "
+ entity.GetAttributeValue<DateTime>("datamodifiedon");
tracingService.Trace(traceMessage);
throw new InvalidPluginExecutionException(traceMessage);
}
}由于更新非常频繁,是否有可能1.更新-2(数据更新8.03 PM)处于预验证阶段。成功验证后,数据库中的实际更新正在进行中。2.更新-1进入预验证阶段。由于更新-2尚未在数据库中提交,在此阶段收到的预实体映像是否仍然是旧值,并让验证通过?
由于其他两个阶段在相同的数据库事务中执行,在运行前或操作后阶段注册这个插件会有帮助吗?
还有其他方法来解决这个并发问题吗?由于更新是通过批处理odata调用启动的,因此不能在请求头中使用eTag预条件。
发布于 2019-07-12 23:59:28
您希望在操作前的步骤上注册这个插件。我认为您对预实体映像可能是脏的(我不确定在事务中是否检索了预映像)有一个合理的担忧,所以不要使用预映像检索记录的新副本,并检查检索到的记录的时间戳和目标上的时间戳。由于您的所有操作都是针对同一个表的同步事务,而且时间戳是该表上的一个字段,所以我认为这将保证没有脏写。
然而,:
如果您的Update1和Update2操作更新了不同的字段,那么现在您可能会遭受反向数据丢失。如果Update1设置字段A和update2设置字段B,则如果在更新字段B之后处理字段A,则对字段A的更改将被忽略。
https://stackoverflow.com/questions/57014426
复制相似问题