前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >sql server对并发的处理-乐观锁和悲观锁

sql server对并发的处理-乐观锁和悲观锁

作者头像
跟着阿笨一起玩NET
发布2022-03-09 17:05:55
6960
发布2022-03-09 17:05:55
举报
文章被收录于专栏:跟着阿笨一起玩NET

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

例如:

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

情景:

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

一般的sql语句:

代码语言:javascript
复制
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,而实际出了两张票。

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

定义解释:

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

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

悲观锁解决方案:

代码语言:javascript
复制
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

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

  从而可以解决上述问题。

乐观锁解决方案:

代码语言:javascript
复制
--首先给表加一列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 '更新失败'

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

悲观锁和乐观锁

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

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

补充:

乐观锁通过自定义行版本号字段方式

更新操作时候,防止同一条数据,同时被多人修改,为每条数据添加一个version字段

//防止同一条数据,同时被多人修改,为每条数据添加一个version字段 1、更新数据之前现获取该条数据的版本号 version字段,version字段设置成默认值0 类型long select version from your_table where id = #{id};

2、更新的时候,要将之前查询出来的version具体值作为条件,同时更新version字段+1 update your_table set user_name = #{userName}, version = version+1 where id = #{id} and version = #{version};

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档