乐观锁和悲观锁的区别
来源:互联网 发布:给二维数组赋初值 编辑:程序博客网 时间:2024/05/22 04:39
最常用的处理多用户并发访问的方法是加锁。当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象。加锁对并发访问的影响体现在锁的粒度上。比如,放在一个表上的锁限制对整个表的并发访问;放在数据页上的锁限制了对整个数据页的访问;放在行上的锁只限制对该行的并发访问。可见行锁粒度最小,并发访问最好,页锁粒度最大,表锁介于2者之间。锁有两种:悲观锁和乐观锁。
悲观锁:并发访问性不好。
顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。
乐观锁:
顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库如果提供类似于write_condition机制的其实都是提供的乐观锁。
如果第二个用户恰好在第一个用户提交更改之前读取了该对象,那么当他完成了自己的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不重新读取该对象并作出更改。这说明在乐观锁环境中,会增加并发用户读取对象的次数。(读锁是共享的,写锁是排他的)。
乐观锁方案:
由于表Order的Status本身就可以起到跟timestamp列一样的效果,修改如下:
update Order
set Status="Y",
where OrderID=@OrderID and Status="wait"
set @rowcount=@@rowcount
程式的修改
var status = GetOrderStatus(orderid); //获取用户充值状态
if(status= "wait")//如果状态为未处理
int rowcount = UpdateOrderStatus(orderid);
if(rowcount= 1) //状态未更新
充值
else //第二次过来的时候,返回行数为0
return "已经充过值"
endif
悲观锁的方式,这次修改的SQL语句不是Update 而是Select
如下:
Select Status from order with (UPDLOCK)
where OrderID= @OrderID
程式完全不用修改:
//获取用户充值状态,第二次过来的时候,如果第一次还未更新,则该订单行还处于锁定状态,因此会等待第一次更新完以将锁释放
var status = GetOrderStatus(orderid);
if(status= "wait")//如果状态为未处理
UpdateOrderStatus(orderid);//则更新状态为已处理
//后台给用户充值的代码
这种方式最简单,程式完全不用修改,只需要在存储过程中加上with (UPDLOCK)即可。
缺点是对大量的并发性能会很差,而且会引起死锁。
当然对于充值这种交易而言,还是可以比较适合的
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 悲观锁和乐观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 悲观锁和乐观锁的区别
- 乐观锁和悲观锁的区别
- 乐观锁和悲观锁的区别
- 悲观锁和乐观锁的区别
- POJ 2253 —— Frogger
- java 8 默认方法和多继承
- MacDown 编辑器 使用
- Java程序员使用的20几个大数据工具
- Android流量监控类 trafficstats
- 乐观锁和悲观锁的区别
- 测试0131
- 101. 支付
- Ubuntu下安装YouCompleteMe插件
- Python2.x和Python3.x的区别
- POJ2502(最短路径dijkstra)
- 图的邻接表
- 每天吃多少才不会胖?食物和卡路里对照表
- OpenPyXL学习