1

一名团队成员在使用旧的内部系统时遇到了问题,其中用户双击网页上的链接可能会导致从浏览器发送两个请求,从而导致在比赛中同一记录的两个数据库插入健康)状况; 最后一个运行失败,主键违规。已经提出并讨论了几种解决方案和技巧:

  1. 在网页上使用 Javascript 通过禁用第一次点击时的链接来减少第二次点击。这是减少问题发生的一种快速简便的方法,但不能完全消除它。

  2. 将服务器端的请求执行包装在事务中。由于相关表上的服务器负载和锁定级别,这被认为过于昂贵的操作。

  3. 捕获失败的插入引发的主键异常,将其识别为这样,然后吃掉它。这具有以下缺点:(a) 供应商锁定,必须知道特定于数据库的异常的细微差别,以及 (b) 可能不记录/处理合法的数据库故障。

  4. #3 的扩展,通过在插入失败时尝试更新记录并检查更新结果以确保它返回 1 条受影响的记录。

是否还有其他未考虑的选项?被忽视的选项是否有优缺点?万恶之中,孰轻孰重?

4

5 回答 5

5

将唯一标识符放在页面上的隐藏字段中。仅接受具有给定唯一标识符的一个响应。

于 2008-10-03T18:22:57.057 回答
2

听起来您可能会滥用 GET 请求来修改服务器状态(尽管不一定是这种情况)。虽然它可能不适合您的情况,但应该说明您应该考虑将链接转换为表单 POST。

于 2008-10-03T18:23:17.603 回答
1

您需要实现同步器令牌模式。

它的工作原理是:在服务器上为每个请求生成一个值(令牌)。然后必须在您的表单提交中包含相同的令牌。收到请求后,将比较服务器令牌和客户端令牌,如果它们相同,您可以继续添加您的记录。然后重新生成服务器端令牌,因此包含旧令牌的后续请求将失败。

在本页的中途有更详尽的解释。

我不确定您使用的是什么技术,但是 Struts 为这种模式提供了框架级别的支持。在此处查看示例

于 2008-11-19T10:37:17.600 回答
0

您似乎已经在那里回答了您自己的问题;#1 似乎是唯一可行的选择。

否则,您真的应该完成所有三个步骤——数据完整性应该在数据库级别处理,但代码中的额外检查(例如显式事务)以避免往返数据库可能对性能有好处。

于 2008-10-03T18:23:12.390 回答
0

REF 您需要实现同步器令牌模式。

这是针对 Javascript/HTML 而不是 JAVA

于 2008-11-19T10:42:49.353 回答