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

例如:

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

情景:

  总共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 '更新失败'

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

悲观锁和乐观锁

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

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

-------------------

但是,查看msdn上的资料,官方说不建议自己加锁:

SQL Server 数据库引擎查询优化器几乎总是会选择正确的锁级别。 建议只在必要时才使用表级锁提示来更改默认的锁行为。 禁止锁级别反过来会影响并发。

对于上面的问题,其实是自己写的sql语句有些不恰当,为什么要把count先查出来呢,直接进行操作就行了啊,不用加upd锁:

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

sql server对并发的处理-乐观锁和悲观锁(转)的更多相关文章

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

    https://www.cnblogs.com/dengshaojun/p/3955826.html sql server对并发的处理-乐观锁和悲观锁 假如两个线程同时修改数据库同一条记录,就会导致后 ...

  2. sql server对并发的处理-乐观锁和悲观锁【粘】

    假如两个线程同时修改数据库同一条记录,就会导致后一条记录覆盖前一条,从而引发一些问题. 例如: 一个售票系统有一个余票数,客户端每调用一次出票方法,余票数就减一. 情景: 总共300张票,假设两个售票 ...

  3. SQL Server 锁机制 悲观锁 乐观锁 实测解析

    先引入一些概念,直接Copy其他Blogs中的,我就不单独写了. 一.为什么会有锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 1.丢失更新 A,B两个用户读同一数据并进行修改,其中 ...

  4. 关于SQL SERVER高并发解决方案

    现在大家都比较关心的问题就是在多用户高并发的情况下,如何开发系统,这对我们程序员来说,确实是值得研究,最近找工作面试时也经常被问到,其实我早有去关心和了解这类问题,但一直没有总结一下,导致面试时无法很 ...

  5. Hibernate事务与并发问题处理(乐观锁与悲观锁)

    目录 一.数据库事务的定义 二.数据库事务并发可能带来的问题 三.数据库事务隔离级别 四.使用Hibernate设置数据库隔离级别 五.使用悲观锁解决事务并发问题 六.使用乐观锁解决事务并发问题 Hi ...

  6. SQL Server提高并发查询效率

    同事写了个程序用创建多个线程使用ado同时对同个数据库进行相同的查询,涉及2张数据表的联查.当线程数非常多的情况下,读取数据的效率就会变得很慢,例如50个线程同时查询大概3000条数据,查询完成后通过 ...

  7. SQL并发处理方案——乐观锁和悲观锁

    (一)乐观锁和悲观锁的概念 悲观锁 在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法.它可以阻 ...

  8. web开发中的两把锁之数据库锁:(高并发--乐观锁、悲观锁)

    这篇文章讲了 1.同步异步概念(消去很多疑惑),同步就是一件事一件事的做:sychronized就是保证线程一个一个的执行. 2.我们需要明白,锁机制有两个层面,一种是代码层次上的,如Java中的同步 ...

  9. Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS

    首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很 ...

随机推荐

  1. StreamSets学习系列之StreamSets的集群安装(图文详解)

    不多说,直接上干货! 若是集群安装 需要在对应节点执行相同的操作. 见 StreamSets学习系列之StreamSets支持多种安装方式[Core Tarball.Cloudera Parcel . ...

  2. linux centos挂载数据盘教程

    一.备份/home/liying目录数据前提条件:电脑重启下,保证服务关闭,以免进程影响操作 a.新建backup目录#cd /#mkdir backup b.把/home/liying/目录下的数据 ...

  3. Spring总结 4.AOP之为对象添加新功能

    Spring除了提供增强原有功能的方法外,还提供了为一个对象引入新功能的方法.如下: package cn.powerfully.service; public interface IService ...

  4. MySQL 50条必练查询语句

    Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 #- ...

  5. 字符串匹配的KMP算法-16张图片看明白

    作者: 阮一峰 日期: 2013年5月 1日 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串"BBC ABCDAB ABCDABCDABDE",我想知道,里面是否包含另 ...

  6. SQL分区表示例

    -- Create tablecreate table TT_FVP_OCR_ADDRESS( id NUMBER not null, waybill_no VARCHAR2(32) not null ...

  7. webpack4 自学笔记一(babel的配置)

    所有代码都可以再我的github上查看,每个文件夹下都会有README.md,欢迎star: https://github.com/Jasonwang911/webpackStudyInit/tree ...

  8. APIO 2018 游记

    上接CTSC 2018 游记 day1 早上大概八九点起来洗了个澡跑到隔壁寝发现 tj 还在??? 原来昨天晚上听错名字了... 下午一起去 wfj 王府井玩,陪李总逛逛奢侈品店... 走了两三个小时 ...

  9. 自定义MVC的Helper扩展方法

    记得在开发ASP.NET时候,也经常性使用C#可以写自己义的扩展方法,如:http://www.cnblogs.com/insus/p/3154363.html 或http://www.cnblogs ...

  10. WPF ContextMenu的使用

    <Grid.ContextMenu > <ContextMenu> <MenuItem Header="增加" Click="MenuIte ...