数据库并发解决方案

转自:http://www.51testing.com/html/00/n-830800.html


在如今分布式、高并发、各种负载纵横天下的时代,支持高访问量成为检验一个系统合不合格的重要标准,然而我们除了在运算过程中要求系统更加效率外,在最终的数据存储过程中也希望其能够准确。

  针对如何解决多线程并发产生的丢失更新问题,本文简单列举一些常见案例及应对措施。

  案例一:

  本地起10个线程,分别执行10次,对数据库的一条记录的sum字段(初始值为0)+1操作,中间的业务逻辑我们忽略掉,如何保证执行完毕后sum的值为100?

  表结构:

字段名 字段类型 可空 字段描述 使用备注
ID BIGINT(20) N 主键ID 无业务含义
SUM NUMBER(20) N 金额 初始值为0

  解决方案:乐观锁机制,利用数据库自身的事务来解决问题,update 表 set sum=sum+#increment#   where id=#id#,适用于一些只更新数量、金额的场景。

  尽量不要采用在后台计算一个最终的sum值,然后通过 update 表 set sum=#sum#  where id=#id#,因为此时在读与写的时间间隔里,很有可能其它的线程已经读过或操作过

  案例二:

  买家操作一笔订单,执行确认收货,假如同一笔订单打开了两个窗口,开始时在一个窗口确认成功,后来在另一个窗口又点了一次,此时应如何解决?

  解决方案:在执行“买家确认收货”操作时,我们通常会首先查出这笔订单,判断当前操作用户是否有执行权限,同时判断当前订单的状态是否是“等待买家确认收货”,。。。,如果满足这些前置条件,才允许后面的业务操作,更新数据库。

  当然,存在另一种可能,如果是通过自动化脚本操作呢?两次操作几乎同时执行,也就是说,两次的前置校验都能顺利通过(因此那时,数据库记录还没来的及更新),此时一个好的解决方案,操作时增加前置条件,比如确认收货的前置条件是“等待买家确认收货”,如果此时订单的状态变成了成功就无法操作。

  update 订单表 set  status="交易成功"  where id=#orderId# and status="等待买家确认收货"

  这样,第二次操作sq条件不满足,也就避免执行两次买家确认收货操作。

  案例三:

  增加前置条件是一个不错的解决方案,但是,不是每个业务都会有前置条件,或者说前置条件不明确,无规则,此时就如何解决?

字段名 字段类型 可空 字段描述 使用备注
ID BIGINT(20) N 主键ID 无业务含义
SUM NUMBER(20) N 金额 初始值为0
version INT(11) N 用于为attribute加锁  

  解决方案:可以借助memcache用到的一种同步机制(CAS),比较并交换,在数据库表增加一个冗余字段,每次操作都会自动+1

  执行业务时,首先会从数据库读取该字段信息,更新业务数据时,会自动比较version的值是否有变化,如果有变化,表示刚才读的信息已变化过,需要重新操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值