sql server对并发的处理-乐观锁和悲观锁(转)
假如两个线程同时修改数据库同一条记录,就会导致后一条记录覆盖前一条,从而引发一些问题。
例如:
一个售票系统有一个余票数,客户端每调用一次出票方法,余票数就减一。
情景:
总共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对并发的处理-乐观锁和悲观锁(转)的更多相关文章
- sql server对并发的处理-乐观锁和悲观锁
https://www.cnblogs.com/dengshaojun/p/3955826.html sql server对并发的处理-乐观锁和悲观锁 假如两个线程同时修改数据库同一条记录,就会导致后 ...
- sql server对并发的处理-乐观锁和悲观锁【粘】
假如两个线程同时修改数据库同一条记录,就会导致后一条记录覆盖前一条,从而引发一些问题. 例如: 一个售票系统有一个余票数,客户端每调用一次出票方法,余票数就减一. 情景: 总共300张票,假设两个售票 ...
- SQL Server 锁机制 悲观锁 乐观锁 实测解析
先引入一些概念,直接Copy其他Blogs中的,我就不单独写了. 一.为什么会有锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 1.丢失更新 A,B两个用户读同一数据并进行修改,其中 ...
- 关于SQL SERVER高并发解决方案
现在大家都比较关心的问题就是在多用户高并发的情况下,如何开发系统,这对我们程序员来说,确实是值得研究,最近找工作面试时也经常被问到,其实我早有去关心和了解这类问题,但一直没有总结一下,导致面试时无法很 ...
- Hibernate事务与并发问题处理(乐观锁与悲观锁)
目录 一.数据库事务的定义 二.数据库事务并发可能带来的问题 三.数据库事务隔离级别 四.使用Hibernate设置数据库隔离级别 五.使用悲观锁解决事务并发问题 六.使用乐观锁解决事务并发问题 Hi ...
- SQL Server提高并发查询效率
同事写了个程序用创建多个线程使用ado同时对同个数据库进行相同的查询,涉及2张数据表的联查.当线程数非常多的情况下,读取数据的效率就会变得很慢,例如50个线程同时查询大概3000条数据,查询完成后通过 ...
- SQL并发处理方案——乐观锁和悲观锁
(一)乐观锁和悲观锁的概念 悲观锁 在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法.它可以阻 ...
- web开发中的两把锁之数据库锁:(高并发--乐观锁、悲观锁)
这篇文章讲了 1.同步异步概念(消去很多疑惑),同步就是一件事一件事的做:sychronized就是保证线程一个一个的执行. 2.我们需要明白,锁机制有两个层面,一种是代码层次上的,如Java中的同步 ...
- Java并发问题--乐观锁与悲观锁以及乐观锁的一种实现方式-CAS
首先介绍一些乐观锁与悲观锁: 悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁.传统的关系型数据库里边就用到了很 ...
随机推荐
- sql字符处理
--Description: 字符处理 --使用: 放到查询分析器里执行就可以了 --示例: select * from dbo.splitstr('12 44 45 50 56 87',' ') o ...
- 【LeetCode题解】347_前K个高频元素(Top-K-Frequent-Elements)
目录 描述 解法一:排序算法(不满足时间复杂度要求) Java 实现 Python 实现 复杂度分析 解法二:最小堆 思路 Java 实现 Python 实现 复杂度分析 解法三:桶排序(bucket ...
- linux下开启、关闭、重启mysql服务
linux下开启.关闭.重启mysql服务命令 一. 启动1.使用 service 启动:service mysql start2.使用 mysqld 脚本启动:/etc/inint.d/mysql ...
- map映照容器(常用的使用方法总结)
map映照容器的数据元素是由一个键值和一个映照数据组成的,键值和映照数据之间具有一一对应的关系.map与set集合容器一样,不允许插入的元素的键值重复. /*关于C++STL中map映照容器的学习,看 ...
- UIView动画下
#import "ViewController.h" @interface ViewController () { UIButton *btn; } @end @implement ...
- Netty 源码剖析之 unSafe.read 方法
目录: NioSocketChannel$NioSocketChannelUnsafe 的 read 方法 首先看 ByteBufAllocator 再看 RecvByteBufAllocator.H ...
- css中添加屏幕自适应方法(rem)
css中添加屏幕自适应方法(rem) 只需要在公共css文件中添加下面代码:设计稿以750px,基础字体为20px为例,兼容性高,使用过程中px转化为rem即可 /*竖屏*/ @media scree ...
- WPF命令(Command)介绍、命令和数据绑定集成应用
要开始使用命令,必须做三件事: 一:定义一个命令 二:定义命令的实现 三:为命令创建一个触发器 WPF中命令系统的基础是一个相对简单的ICommand的接口,代码如下: public interfac ...
- JS DOM操作(三) Window.docunment对象——操作属性
属性:是对象的性质与对象之间关系的统称.HTML中标签可以拥有属性,属性为 HTML 元素提供附加信. 属性总是以名称/值对的形式出现,比如:name="value". 属性值始终 ...
- Nett的Http表头赋值
DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseSta ...