记一次遇到由于重复提交导致的问题

  • 需求
  • 问题
  • 解决和复盘

这是新手期间第一个上线功能搞出的bug,同时也明白了一个道理:1. 线上环境总是复杂的,不可预知的,一定要做好各种准备; 2. 重要的功能要做放重复提交;3. 基础要打打牢。

需求

需求其实很简单,就是一个修改密码的入口,用户输入提交表单后,如果之前没有设置过密码,则设置,否则修改。然后验证密码的逻辑就不用说了,查出表里的密码,然后对比。

项目是ibatis+oralce,之前DAO的逻辑如下

...
if (isNotExists()){
    insertPassword;
} else {
    updatePassword;
}

isNotExists()方法就是select看是否存在记录。

public Map queryPassword(Map param) throws DAOException {
    return sqlMapClientTemplate.queryForObject(param);
}

问题

某一天中午突然来了告警日志,发现在queryPassword这个方法这里抛出了too many results异常,很显然,本应该每个用户只存在一条记录的,查出了多条。让运维同事查出数据,果然有一个用户,存在3条记录。查看原代码逻辑,那很显然是在判断是否存在记录这里同时来了三个请求,然后三个线程都发现该用户对应的记录是空的,于是同时插入了三条记录。(后来通过电话回访用户,说当时手机页面卡了,于是瞎点一通,可能页面卡了,等反应后一下子发出去多条请求。)

解决和复盘

  • 首先线上问题紧急的解决方案就是删掉记录就OK了。
  • 然后这种if ... then...的用法是非常危险的,一来一回,在并发情况下就出现问题了。当时想着改个密码对同一个用户哪儿来的多并发,先就这样干吧,事实证明线上环境的复杂是永远超出自己预知的。对于这种场景,最好使用oralce提供的merge方法,把事务处理交给oracle,出错的概率更小一些。
    merge into pwd_table t
    using dual
    on (t.id = #id#)
    when matched then
        update pwd_table t set t.pwd = #pwd#
        where t.id = #id#
    when not matched then
        insert into pwd_table t values(#id#, #pwd#)
  • 做防重复提交限制,考虑到用户的群体,最简单的是在用户提交请求得到响应之前,按钮置为diabled状态
  • 基础一定要打好,当时就是对merge了解不深没有使用,要多学习PL/SQL的东西

原文地址:https://www.cnblogs.com/dirac/p/8640406.html

时间: 2024-10-16 22:52:44

记一次遇到由于重复提交导致的问题的相关文章

web开发中禁止因为网速慢导致重复提交数据

var checkSubmitFlg = false;  function check() {                if (!checkSubmitFlg) {                    checkSubmitFlg = true;                    return true;                }                else {                    alert('禁止重复提交!');               

【ASP.NET】 【防止连续多次点击提交按钮 导致页面重复提交】

最近做项目遇到了这样的情况: 公司网络比平常慢了不少,在点击保存按钮提交页面后需等待挺长的一段时间,忍不住手贱点多了几次,当提交完成后发现数据库语句执行异常. 两种验证方式: 第1种: aspx页面按钮: <asp:Button ID="btnSumbit" runat="server" Text="提交" onclick="btnSumbit_Click" /> Page_Load 事件: btnSumbit.A

表单重复提交问题

一.常见的重复提交问题  a>点击提交按钮两次.  b>点击刷新按钮.  c>使用浏览器后退按钮重复之前的操作,导致重复提交表单.  d>使用浏览器历史记录重复提交表单.  e>浏览器重复的HTTP请求. 二.防止表单重复提交原理 提交表单的时候提交一份随机的字符串或随机数字等等,再把这个随机的数据存到request里面,然后把表单数据提交,在后台验证的时候判断提交的这两份额外的数据是否一致,如果一致,则把其中一份删除掉,这么做的目的是防止再次提交,继续进行操作,如果不一致,

防止表单重复提交

客户端防止表单重复提交: 不足之处:用户单击”刷新”,或单击”后退”再次提交表单,将导致表单重复提交 <script type="text/javascript"> //方式一 var iscommitted = false; function dosubmit(){ if(!iscommitted){ iscommitted = true; return true; }else{ return false; } } //方式二 function dosubmit(){ d

struts2 文件的上传下载 表单的重复提交 自定义拦截器

文件上传中表单的准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置为 post 需添加 <input type=“file”> 字段. Struts 对文件上传的支持 在 Struts 应用程序里, FileUpload 拦截器和 Jakarta Commons FileUpload 组件可以完成文件的上传. 步骤:1. 在 Jsp 页面的文件上传表单里使用

php 解决和避免form表单重复提交的方法

在提交表单的时候,可能遇到网速等导致页面突然加载变慢,用户重复地点击提交按钮,将在数据库产生多条数据,导致不可控情况. 比如下面的情况就会导致表单重复提交: 点击提交按钮两次. 点击刷新按钮. 使用浏览器后退按钮重复之前的操作,导致重复提交表单. 使用浏览器历史记录重复提交表单. 浏览器重复的HTTP请求. 网页被恶意刷新. 下面是几种解决的方法: 一:利用js设置按钮点击后变成灰色 $(document).ready(function(){ $(input:submit).click(){ s

[PHP]防止表单重复提交的几种方法

--------------------------------------------------------------------------------------------------- 1. 使用JS让按钮在点击一次后禁用(disable).=> 防止多次点击发生,实现方式较简单. 缺点:若客户端禁止JavaScript脚本,则失效. 2. 在提交成功后执行页面重定向(redirect).=> 转到提交成功信息页面. 特点:避免F5重复提交,消除浏览器前进和后退按导致的同样问题.

表单重复提交--笔记

同一个表单中的内容多次提交到服务器中. 第一种情况:    提交完表单以后,不做其他操作,直接刷新页面,表单会提交多次.    - 这种情况产生的根本原因是,Servlet处理完请求以后,直接转发到目标页面.    - 这样整一个业务,只发送了一次请求,那么当你在浏览器中点击刷新按钮或者狂按f5会一直都会刷新之前的请求 解决方案:     使用重定向跳转到目标页面 第二种情况:    在提交表单时,如果网速较差,可能会导致点击提交按钮多次,这种情况也会导致表单重复提交.    - 产生的原因:是

form表单重复提交问题

导致表单重复提交的原因是:第一次提交的表单会被缓存到内存中,直到页面下次提交或页面关闭或转向其他页面时才消失.在自调用返回时,内存中的数据依然在,这时页面中的判断提交的代码依然可以检测到提交的值,顾会产生重复提交的效果. 解决方法 Ⅰ重定向,页面提交后转到另一个页面而不是本页面 Ⅱ提交表单后提交按钮变灰/隐藏提交按钮 Ⅲ增加令牌token 访问页面前产生token public void toStart(HttpServletRequest req, HttpServletResponse re