双击双插入分辨率?

时间:2008-10-03 18:19:28

标签: insert primary-key double-click

团队成员遇到了旧内部系统的问题,用户双击网页上的链接会导致从浏览器发送两个请求,导致同一记录中的两个数据库插入在竞争条件下;最后一个运行失败,主键违规。已经提出并讨论了几种解决方案和黑客:

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

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

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

  4. #3的扩展名,如果插入失败则尝试更新记录并检查更新结果以确保它返回1个受影响的记录。

  5. 其他选项是否未被考虑过?是否存在被忽视的选项的优缺点?所有邪恶中哪一个较小?

5 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

您需要实现Synchronizer Token模式。

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

对于this page中途有一个更彻底的解释。

我不确定您使用的是哪种技术,但Struts为此模式提供了框架级支持。请参见示例here

答案 3 :(得分:0)

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

否则,您应该完全执行所有三个步骤 - 数据完整性应在数据库级别处理,但代码中的额外检查(例如显式事务)以避免往返数据库可能有利于性能。 / p>

答案 4 :(得分:0)

REF您需要实现Synchronizer Token模式。

这适用于Javascript / HTML而不是JAVA