资讯专栏INFORMATION COLUMN

MYSQL使用锁解决并发下的更新丢失问题

brianway / 1847人阅读

摘要:在层常用的悲观锁实现方式是加一个排他锁。所以为了防止更新丢失可以在时加上加锁这样就可以阻止其余事务的但注意无法阻止这样在操作提交前操作无法获得排他锁,从而避免对的重复更新导致的更新丢失。

更新丢失是指并发下两次更新同时进行,后一次更新覆盖了前一次更新的情况,更新丢失是数据没有保证一致性导致的。
举个栗子:

用户A在银行卡有100元钱,某一刻用户B向A转账50元(称为B操作),同时有用户C向A转账50元(称为C操作);

B操作从数据库中读取他此时的余额100,计算新的余额为100+50=150

C操作也从数据库中读取他此时的余额100,计算新的余额为100+50=150

B操作将balance=150写入数据库,之后C操作也将balance=150写入数据库

最终A的余额变为150

上面的例子,A同时收到两笔50元转账,最后的余额应该是200元,但却因为并发的问题变为了150元,原因是B和C向A发起转账请求时,同时打开了两个数据库会话,进行了两个事务,后一个事务拿到了前一个事务的中间状态数据,导致更新丢失。
常用的解决思路有两种:

加锁同步执行

update前检查数据一致性

悲观锁

顾名思义,悲观锁在读取数据的时候都会认为会有别人去修改,于是在取数据的时候会对当前数据加一个锁,在操作结束前,不允许其余操作更改。要注意悲观锁和乐观锁都是业务逻辑层次的定义,不同的设计可能会有不同的实现。在mysql层常用的悲观锁实现方式是加一个排他锁。
排他锁
查阅资料很多对排他锁的解释是:“排他锁通过在事务中使用select xx for update语句来实现,排他锁会在当前行加一个行级锁,在当前事务提交前,其余事务无法进行update操作。”

然而实际上并不是这样,实际上是加了排他锁的数据,在释放锁(事务结束)之前其他事务不能再对该数据加锁
排他锁之所以能阻止update,delete等操作是因为update,delete操作会自动加排他锁

也就是说即使加了排他锁也无法阻止select操作。而select XX for update 语法可以对select 操作加上排他锁。所以为了防止更新丢失可以在select时加上for update加锁 这样就可以阻止其余事务的select for update(但注意无法阻止select)
example:

begin;
select * from account where id = 1 for update;
update account set balance=150 where id =1;
commit;

这样在B操作提交前,C操作无法获得排他锁,从而避免对account的重复更新导致的更新丢失。

乐观锁

乐观锁是指在获取数据时候不加锁,乐观的认为操作不会有冲突,在update的时候再去检查冲突。
example:

begin;
select balance from account where id=1;
-- 得到balance=100;然后计算balance=100+50=150
update account set balance = 150 where id=1 and balance = 100;
commit;

如上,如果sql在执行的过程中发现update的affected为0 说明balance不等于100即该条数据有被其余事务更改过,此时业务上就可以返回失败或者重新select再计算

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/17670.html

相关文章

  • MYSQL使用解决发下更新丢失问题

    摘要:在层常用的悲观锁实现方式是加一个排他锁。所以为了防止更新丢失可以在时加上加锁这样就可以阻止其余事务的但注意无法阻止这样在操作提交前操作无法获得排他锁,从而避免对的重复更新导致的更新丢失。 更新丢失是指并发下两次更新同时进行,后一次更新覆盖了前一次更新的情况,更新丢失是数据没有保证一致性导致的。举个栗子: 用户A在银行卡有100元钱,某一刻用户B向A转账50元(称为B操作),同时有用户...

    leanxi 评论0 收藏0
  • MYSQL使用解决发下更新丢失问题

    摘要:在层常用的悲观锁实现方式是加一个排他锁。所以为了防止更新丢失可以在时加上加锁这样就可以阻止其余事务的但注意无法阻止这样在操作提交前操作无法获得排他锁,从而避免对的重复更新导致的更新丢失。 更新丢失是指并发下两次更新同时进行,后一次更新覆盖了前一次更新的情况,更新丢失是数据没有保证一致性导致的。举个栗子: 用户A在银行卡有100元钱,某一刻用户B向A转账50元(称为B操作),同时有用户...

    yanest 评论0 收藏0
  • MySQL InnoDB机制全面解析分享

    摘要:一条记录操作完成,再读取下一条记录,直至没有满足条件的记录为止。 写在前面:在设计新零售供应链wms(仓库管理系统)库存模块时,为了防止并发情况对库存的影响,查阅了一些资料,对InnoDB锁机制有了更全面的了解,在此做出分享,如有疏漏望不吝指正,愿共同进步!(此篇为1.0版本,后续随理解深入,会逐步迭代完善~) 一、为什么要加锁 锁机制用于管理对共享资源的并发访问。 当多个用户并发地存...

    stormzhang 评论0 收藏0
  • 「Python 面试」第五次更新

    摘要:也就是说当使用字符型存储数据后,该数据转换为二进制时的长度超过了位,那么该数据将不会完整存储,会丢失一部分数据。 showImg(https://segmentfault.com/img/bVbuYxg?w=3484&h=2480); 阅读本文大约需要 8 分钟。 写在前面 数据库打算只写 MySQL,Redis 两部分,不会很细,主要以面试题为主。这次写的是 MySQL 篇。 1.说...

    zhunjiee 评论0 收藏0
  • MySQL和行机制

    摘要:对于和语句,会自动给涉及数据集加排他锁对于普通语句,不会加任何锁当然我们也可以显示的加锁共享锁排他锁和的最大不同点有两个一,支持事务二,默认采用行级锁。排他锁排他锁,也称写锁,独占锁,当前写操作没有完成前,它会阻断其他写锁和读锁。 MySQL 表锁和行锁机制 行锁变表锁,是福还是坑?如果你不清楚MySQL加锁的原理,你会被它整的很惨!不知坑在何方?没事,我来给你们标记几个坑。遇到了可别...

    luckyyulin 评论0 收藏0

发表评论

0条评论

brianway

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<