单个故障是否会使批量操作失败?


11

我正在使用的API中有一个批量删除操作,该操作接受ID数组:

["1000", ..., "2000"]

我可以按照自己的意愿随意执行删除操作,因此我决定使整个事务具有事务性:也就是说,如果单个ID无效,则整个请求将失败。我将其称为严格模式。

try{
savepoint = conn.setSavepoint();

for(id : IDs)
    if( !deleteItem(id) ){
        conn.rollback(savepoint);
        sendHttp400AndBeDoneWithIt();
        return;
    }

conn.commit();
}

备选方案(在软件套件中的其他位置实现)是尽我们所能在后端进行操作,并报告阵列中的故障。该软件的这一部分处理的请求较少,因此从理论上讲,响应不会成为一个巨大的数组。


资源贫乏的服务器中最近发生的一个错误使我再次查看代码,现在我在质疑最初的决定-但是这次,我更多地是出于业务需求而不是最佳实践的动力。例如,如果我未能通过整个请求,则用户将不得不重试,而如果删除了许多项目,则用户可以完成操作,然后要求管理员执行其余操作(在我修复错误的同时) !)。这将是许可模式。

我尝试在网上寻找有关此事的一些指导,但我空手而归。所以我来找你:这种性质的批量操作最期望什么?我应该坚持更严格,还是应该更宽容?


9
这取决于。什么时候应该删除不删除的代价是什么?(成本被定义为不良数据,头痛,不良行为,管理员修复它所花费的时间等)。这可以接受吗?如果您可以承受不让一切都失败的后果,那就去吧。如果这会引起太多问题,请不要这样做。您知道您的软件及其后果,因此您必须做出判断。
Becuzz

1
@Becuzz的代价是用户注意到一两个剩菜并为此开了罚单;当前情况是“ omg删除已损坏”。幸运的是,用户在走廊上,所以这次并不是太大的问题。关键是,我喜欢尽可能地做正确的事,并且拥有十多年历史的代码库,上帝知道有些事情可以正确完成
Rath

我认为这还取决于您是否需要可伸缩性。如果您不打算拥有很多ID,那也没关系。如果您打算拥有一百万个ID,或者还不能确定它不会更好,那么您可以花一个小时删除ID,只是由于1个无效ID而使其完全重置。
imnota4

1
@ imnota4我没考虑过的一个很好的观点。UI将请求限制为最多约250个,但后端没有限制。我可以请你重新发表评论作为答案吗?
拉斯

1
允许模式还使管理员的工作更加轻松,因为他们不需要使用所有ID堆栈重现失败。在响应中告知每个错误的原因也可能很有用。查看原因,最终用户可能会解决此问题,而不会遇到“损坏的删除损坏”的故障单。
2016年

Answers:


9

可以对删除端点执行“严格”或“不错”的版本,但是您需要清楚地告诉用户发生了什么。

我们正在对此端点执行删除操作。可能DELETE /resource/bulk/或类似的东西。我不挑剔 这里重要的是,无论您决定严格还是好,都需要准确地报告发生的情况。

例如,我使用的API的DELETE /v1/student/端点接受批量ID。我们会在测试过程中定期发出请求,得到200答复并假设一切都很好,后来才发现列表中的每个人都在数据库中,但他们仍然处于错误状态(设置为非活动状态)或由于错误而实际上未被删除,弄乱了将来的电话,GET /v1/student因为我们得到了我们不期望的数据。

解决方案出现在以后的更新中,该更新向具有未删除ID的响应添加了正文。就我所知,这是一种最佳实践。

最重要的是,无论您做什么,都要确保提供一种让最终用户知道发生了什么以及可能为什么发生的方法。IE,如果我们选择严格的格式,则响应可能是400 - DELETE failed on ID 1221 not found。如果我们选择了一个“不错”的版本,那可能是207 - {message:"failed, some ids not deleted", failedids:{1221, 23432, 1224}}(请原谅我糟糕的json格式)。

祝好运!


6
207 Multi-Status可能适合部分失败响应
Richard Tingle

1
我们去了!我真的不记得了!我要继续更新答案,因为这实际上符合标准。
亚当·威尔斯

2

一个应该严格和宽容。

通常,大负载分为两个阶段:

  • 验证方式
  • 载入中

在验证阶段,将严格检查每条记录,以确保其符合数据规范的要求。只需几秒钟,您就可以轻松检查1000条记录中的10条。有效记录放置在要加载的新文件中,标记无效的记录并将其删除,通常将它们放置在单独的文件(跳过文件)中。然后,通知会在验证失败的记录上发送出去,以便进行检查和诊断以进行故障排除。

数据通过验证后,便会加载。通常,如果它足够大,可以避免长时间运行的事务,或者如果发生故障,将更容易恢复,将分批加载。批处理大小取决于数据集的大小。如果一个只有几千条记录,那么一批就可以了。在这里,您可以容忍失败,但是您可能需要设置一个失败的批处理阈值来停止整个操作。如果[N]个批次失败,则可能会停止整个操作(如果服务器已关闭或类似原因)。通常,由于数据已经过验证,此时不会出现任何故障,但是如果是由于环境问题或其他原因,则只需重新加载失败的批次即可。这使恢复变得容易一些。


我不根据数据库值验证ID,只是尝试删除它们并查看其进展,否则将永远花费。N次失败后中止似乎是一个非常合理的建议,+ 1
rath 16-10-13

2

单个故障是否会使批量操作失败?

没有一个规范的答案。需要检查用户的需求和后果,并权衡取舍。OP提供了一些必需的信息,但是这是我将如何进行的操作:

问题1:“如果单个删除失败,对用户会有什么后果?”

答案应该驱动其余的设计/实施行为。

如果按照OP的描述,只是用户注意到异常并打开故障单,但其他方面不受影响(未删除的项目不会影响后续任务),那么我会自动接受自动通知给你。

如果失败的删除需要在用户继续操作之前得到解决,那么严格的选择显然是可取的。

为用户提供选项(例如,本质上是默认为严格或允许的忽略失败标志)可能是最用户友好的方法。

问题2:“如果在数据存储区中仍有未删除项目的情况下执行后续任务,会不会有数据一致性/一致性问题?”

同样,答案将驱动最佳设计/行为。是->严格,否->允许,也许->严格或用户选择(特别是如果可以依靠用户来准确确定结果)。


0

我认为这取决于您是否需要可伸缩性。如果您不打算拥有很多ID,那也没关系。如果您打算拥有一百万个ID,或者还不能确定它不会更好,那么您可以花一个小时删除ID,只是由于1个无效的ID而使其完全重置。


-1

我要说的一个重点是删除大量内容意味着什么。

这些ID在某种程度上在逻辑上相关,还是仅仅是为了方便/性能-批量分组?

万一发生某种情况,即使是松散地连接,我也会去争取strict。如果只是批处理模式(例如,用户在工作的最后几分钟单击“保存”,然后才发送批处理),那么我将选择该permissive版本。

如其他答案所述:无论如何,请告诉“用户”确切的情况。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.