悲观锁(Pessimistic Locking)
悲观锁,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。
一个典型的倚赖数据库的悲观锁调用:
select * from account where name=”tong” for update
这条sql 语句锁定了account 表中所有符合检索条件(name=”tong”)的记录。本次事务提交之前(事务提交时会释放事务过程中的锁),外界无法修改这些记录。
锁类型:
X-排他锁:如果对象被一个排他锁给琐住,那么按照锁的相容性来讲其他会话就不能够在对这个会话所加锁的对象加任何的锁。
S-共享锁:如果对象被一个共享锁给锁住,那么按照锁的相容性来讲其他会话除了S锁本身,都不能对这个会话所加锁的对象加任何的锁。
按照粒度的大小锁可以分为行级锁,表级锁,页级锁。
行级锁是事务级的.如果一个事务要修改被另一个事务更新还没有提交的数据时,他就会阻塞.等待锁的释放。通常的DML操作(SELECT…FOR UPDATE、INSERT、UPDATE、DELETE),在表级获得的只是意向锁(RS或RX),其真正的封锁粒度还是在行级。
SQL语句 |
表锁模式 |
允许的锁模式 |
Select * from table_name…… |
无 |
RS、RX、S、SRX、X |
Insert into table_name…… |
RX |
RS、RX |
Update table_name…… |
RX |
RS、RX |
Delete from table_name…… |
RX |
RS、RX |
Select * from table_name for update |
RS |
RS、RX、S、SRX |
lock table table_name in share mode |
S |
RS、S |
lock table table_name in exclusive mode |
X |
无 |
乐观锁(Optimistic Locking)
相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。但随之而来的就是数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受。如一个金融系统,当某个操作员读取用户的数据,并在读出的用户数据的基础上进行修改时(如更改用户帐户余额),如果采用悲观锁机制,也就意味着整个操作过程中(从操作员读出数据、开始修改直至提交修改结果的全过程,甚至还包括操作员中途去煮咖啡的时间),数据库记录始终处于加锁状态,可以想见,如果面对几百上千个并发,这样的情况将导致怎样的后果。乐观锁机制在一定程度上解决了这个问题。乐观锁,大多是基于数据版本(Version)记录机制实现。何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个“version”字段来实现。
读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。对于上面修改用户帐户信息的例子而言,假设数据库中帐户信息表中有一个version字段,当前值为1;而当前帐户余额字段(balance)为$100。
1 操作员A 此时将其读出(version=1),并从其帐户余额中扣除$50($100-$50)。
2 在操作员A操作的过程中,操作员B也读入此用户信息(version=1),并从其帐户余额中扣除$20($100-$20)。
3 操作员A完成了修改工作,将数据版本号加一(version=2),连同帐户扣除后余额(balance=$50),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录version更新为2。
4 操作员B完成了操作,也将版本号加一(version=2)试图向数据库提交数据(balance=$80),但此时比对数据库记录版本时发现,操作员B提交的数据版本号为2,数据库记录当前版本也为2,不满足“提交版本必须大于记录当前版本才能执行更新“的乐观锁策略,因此,操作员B 的提交被驳回。
这样,就避免了操作员B 用基于version=1 的旧数据修改的结果覆盖操作员A的操作结果的可能。
相关推荐
Hibernate 锁机制_悲观锁和乐观锁 Hibernate 锁机制是指在... Hibernate 的锁机制可以分为悲观锁和乐观锁两种,悲观锁通过数据库层次的锁定来实现,而乐观锁通过应用程序上的逻辑实现版本控制的方法来维护正确的数据。
并发控制—悲观锁和乐观锁
Java 中的悲观锁和乐观锁的实现 纯开发技巧。
悲观锁和乐观锁的技术对比和应用.docx
当前的PPT总共56页,从锁的介绍,到java锁(lock、synchronor、aqs)到分布式锁 redis、zk、数据库的悲观锁和乐观锁都有涉及,算是比较完整的一个PPT,适合涉及到锁相关的专题讲座,以及自学的PPT,后面有机会会开...
十三、关于悲观锁和乐观锁
36谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
NULL 博文链接:https://cdxs2.iteye.com/blog/1938245
主要介绍了Hibernate实现悲观锁和乐观锁的有关内容,涉及hibernate的隔离机制,以及实现悲观锁和乐观锁的代码实现,需要的朋友可以了解下。
所谓乐观锁,重视假设最好的情况,每次去拿数据都认为别人不会修改,所以不会上锁,但是会在更新时判断一下在此期间这个数据有没有更改,使用版本号机制和CAS算法实现,乐观锁适用于多读的应用类型,这样可以提高...
介绍数据库事务的定义和事务带来的问题,详细讲解乐观锁与悲观锁的区别
NULL 博文链接:https://12345678.iteye.com/blog/721836
主要介绍了thinkPHP框架乐观锁和悲观锁,结合实例形式分析了框架乐观锁和悲观锁的原理及thinkPHP相关实现技巧,需要的朋友可以参考下
很好的描述Hibernate的悲观锁和乐观锁,
在关系型数据库中,悲观锁与乐观锁是解决资源并发场景的解决方案,接下来将详细讲解:magnifying_glass_tilted_right:一下这两个并发解决方案的实际使用及优缺点。 首先定义一下数据库,做一个最简单的库存表,如下...
锁机制可以分为悲观锁和乐观锁两种。 一、悲观锁 悲观锁是一种对数据的修改抱有悲观态度的并发控制方式。它认为数据被并发修改的概率比较大,所以需要在修改之前先加锁,以防止并发的发生。悲观锁在数据库中的应用...
主要给大家介绍了关于Mysql悲观锁和乐观锁使用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Mysql具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
乐观锁和悲观锁 在编程世界中,锁是五花八门的,每种锁的加锁开销以及应用场景也可能会不同。如何用好锁,也是程序员的基本素养之一了。在高并发的场景下,如果选择了合适的锁,则会大大提高系统的性能,否则性能会...
详细介绍了Oracle中乐观锁、悲观锁的原理及应用,并有实例