当前位置:   article > 正文

【MySQL(十六)】更新丢失 解决方案_mysql跟新时tinyint跟新失败

mysql跟新时tinyint跟新失败

一个比较见的业务场景,先从表里读一条数据的一列,然后在内存中计算该列的新值,最后再update新值到表里:

  1. select data from table where id = xxx; // db
  2. newdate = data + 1; // 内存
  3. update table set data = newdata where id = xxx; // db

这样的三条语句,如果不加事务,可能会有更新丢失的问题。就是多个事务并发修改同一行数据时,读到了相同的值,然后分别更新,那么就会丢失前一次更新;

为啥要分三条?直接update set data = data + 1貌似就行?

这里的+1只是示例,实际上这个1可能需要根据一些特定的业务逻辑计算出来,所以必须要先读到内存才能计算到新值;

怎么解决更新丢失问题?

这里介绍两种方案:

1.使用事务+锁定读

  1. begin;
  2. select data from table where id = xxx for update; // db
  3. newdate = data + 1; // 内存
  4. update table set data = newdata where id = xxx; // db
  5. commit;

这里首先使用了begin语法,将上述三个步骤放入到事务中,并且读取时使用了for update的锁定读方式,这样一旦读到了数据,那么就会加X锁,别的事务便无法读该行数据或者修改该行数据了。

2.不使用事务,cas更新

  1. // for loop begin
  2. select data from table where id = xxx; // db
  3. newdate = olddata + 1;// 内存
  4. update table set data = newdata where id = xxx and data = olddata; // db
  5. // for loop end

这个方案不需要事务,但是在update时,加上了cas的判断,整套逻辑需要放在循环中完成,不断cas尝试直到更新成功,需要业务逻辑来处理cas更新,并且可能需要设置最大重试次数,防止一直自旋;

貌似在高并发场景下,使用方案一更好些,毕竟方案二冲突的概率比较大,一直重复select update也会影响性能;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/272767
推荐阅读
相关标签
  

闽ICP备14008679号