zoukankan      html  css  js  c++  java
  • 通过乐观锁(版本号)降低并发时的锁竞争问题

     在高并发下,经常需要处理SELECT之后,在业务层处理逻辑,再执行UPDATE的情况。

      若两个连接并发查询同一条数据,然后在执行一些逻辑判断或业务操作后,执行UPDATE,可能出现与预期不相符的结果。

      在不使用悲观锁与复杂SQL的前提下,可以使用乐观锁处理该问题,同时兼顾性能。

      场景模拟:

      假设一张表两个字段,一个id,一个use_count。
    表里存了100个id,每个id对应自己的use_count。

      当id每使用一次,use_count要加1。当use_count大于1000时,这个id就不能在被使用了(换句话说 无法从数据库中查出)。

      在高并发情况下,会遇到一种问题:假设数据表中有一条记录为:id=123456, use_count=999
      A与B两个连接并发查询这个id=123456,都执行下列SQL:

    SELECT * FROM table WHERE id=123456 and use_count < 1000;

      A先执行,得到id=123456的use_count是999,之后在程序里做了一些逻辑判断或业务操作后执行SQL:

    UPDATE table SET use_count + 1 WHERE id=123456;

      在A做判断且没有update之前,B也执行了查询SQL,发现use_count是999,之后它也会执行SQL:

    UPDATE table SET use_count + 1 WHERE id=123456;

      但是,事实上B不应该取得这个id,因为A已经是第1000个使用者。

      处理步骤如下:

      1、添加第3个字段version,int类型,default值为0。version值每次update时作加1处理。

    ALTER TABLE table ADD COLUMN version INT DEFAULT '0' NOT NULL AFTER use_count;

      2、SELECT时同时获取version值(例如为3)。

    SELECT use_count, version FROM table WHERE id=123456 AND use_count < 1000;

      3、UPDATE时检查version值是否为第2步获取到的值。

    UPDATE table SET version=4, use_count=use_count+1 WHERE id=123456 AND version=3;

      如果UPDATE的记录数为1,则表示成功。
    如果UPDATE的记录数为0,则表示已经被其他连接UPDATE过了,需作异常处理。

  • 相关阅读:
    FZU 2098 刻苦的小芳(卡特兰数,动态规划)
    卡特兰数总结
    FZU 1064 教授的测试(卡特兰数,递归)
    HDU 4745 Two Rabbits(区间DP,最长非连续回文子串)
    Java 第十一届 蓝桥杯 省模拟赛 正整数的摆动序列
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 反倍数
    Java 第十一届 蓝桥杯 省模拟赛 凯撒密码加密
    Java 第十一届 蓝桥杯 省模拟赛 凯撒密码加密
  • 原文地址:https://www.cnblogs.com/zongyl/p/6021097.html
Copyright © 2011-2022 走看看