zoukankan      html  css  js  c++  java
  • 数据库对并发的处理-乐观锁与悲观锁

    假如两个线程同时修改数据库同一条记录,就会导致后一条记录覆盖前一条,从而引发一些问题。

    例如:

      一个售票系统有一个余票数,客户端每调用一次出票方法,余票数就减一。

    情景: 

      总共300张票,假设两个售票点,恰好在同一时间出票,它们做的操作都是先查询余票数,然后减一。

    一般的sql语句:

      

    declare @count as int
     
    begin tran
        select @count=count from ttt
        WAITFOR DELAY '00:00:05' --模拟并发,故意延迟5秒
        update ttt set count=@count-1
    commit TRAN
     
    SELECT * FROM ttt

      问题就在于,同一时间获取的余票都为300,每个售票点都做了一次更新为299的操作,导致余票少了1,而实际出了两张票。

      打开两个查询窗口,分别快速运行以上代码即可看到效果。

    定义解释:

      悲观锁:相信并发是绝大部分的,并且每一个线程都必须要达到目的的。

      乐观锁:相信并发是极少数的,假设运气不好遇到了,就放弃并返回信息告诉它再次尝试。因为它是极少数发生的。

    悲观锁解决方案:

      

    declare @count as int
     
    begin tran
        select @count=count from tb WITH(UPDLOCK)
       WAITFOR DELAY '00:00:05' --模拟并发,故意延迟5秒
        update tb set count=@count-1
    commit tran

      在查询的时候加了一个更新锁,保证自查询起直到事务结束不会被其他事务读取修改,避免产生脏数据。

      从而可以解决上述问题。

    乐观锁解决方案:

    --首先给表加一列timestamp
     
    ALTER TABLE ttt ADD timesFlag TIMESTAMP NOT null
     
    然后更新时判断这个值是否被修改
    declare @count as int
    DECLARE @flag AS TIMESTAMP
    DECLARE @rowCount AS int
    begin tran
        select @count=COUNT,@flag=timesflag from ttt
        WAITFOR DELAY '00:00:05'
        update ttt set count=@count-1 WHERE timesflag=@flag --这里加了条件
        SET @rowcount=@@ROWCOUNT  --获取被修改的行数
    commit TRAN
     
    --对行数进行判断即可
     
    IF @rowCount=1
        PRINT '更新成功'
    ELSE
        PRINT '更新失败'

      这便是乐观锁的解决方案,可以解决并发带来的数据错误问题,但不保证每一次调用更新都成功,可能会返回'更新失败'

    悲观锁和乐观锁

      悲观锁一定成功,但在并发量特别大的时候会造成很长堵塞甚至超时,仅适合小并发的情况。

      乐观锁不一定每次都修改成功,但能充分利用系统的并发处理机制,在大并发量的时候效率要高很多。

  • 相关阅读:
    导包路径
    django导入环境变量 Please specify Django project root directory
    替换django的user模型,mysql迁移表报错 django.db.migrations.exceptions.InconsistentMigrationHistory: Migration admin.0001_initial is applied before its dependen cy user.0001_initial on database 'default'.
    解决Chrome调试(debugger)
    check the manual that corresponds to your MySQL server version for the right syntax to use near 'order) values ('徐小波','XuXiaoB','男','1',' at line 1")
    MySQL命令(其三)
    MySQL操作命令(其二)
    MySQL命令(其一)
    [POJ2559]Largest Rectangle in a Histogram (栈)
    [HDU4864]Task (贪心)
  • 原文地址:https://www.cnblogs.com/kongsq/p/5841397.html
Copyright © 2011-2022 走看看