乐观锁、悲观琐、死锁的区别

  锁:我们知道,最常用的处理多用户并发访问的方法是加锁。当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象。加锁对并发访问的影响体现在锁的粒度上。比如,放在一个表上的锁限制对整个表的并发访问;放在数据页上的锁限制了对整个数据页的访问;放在行上的锁只限制对该行的并发访问。可见行锁粒度最小,并发访问最好,页锁粒度最大,表锁介于2者之间。

  锁有两种:悲观锁和乐观锁。悲观锁假定其他用户企图访问或者改变你正在访问、更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁。悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长,这样可能会长时间的限制其他用户的访问,也就是说悲观锁的并发访问性不好。与悲观锁相反,乐观锁则认为其他用户企图改变你正在更改的对象的概率是很小的,因此乐观锁直到你准备提交所作的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。可见乐观锁加锁的时间要比悲观锁短,乐观锁可以用较大的锁粒度获得较好的并发访问性能。但是如果第二个用户恰好在第一个用户提交更改之前读取了该对象,那么当他完成了自己的更改进行提交时,数据库就会发现该对象已经变化了,这样,第二个用户不得不重新读取该对象并作出更改。这说明在乐观锁环境中,会增加并发用户读取对象的次数。

  从数据库厂商的角度看,使用乐观的页锁是比较好的,尤其在影响很多行的批量操作中可以放比较少的锁,从而降低对资源的需求提高数据库的性能。再考虑聚集索引。在数据库中记录是按照聚集索引的物理顺序存放的。如果使用页锁,当两个用户同时访问更改位于同一数据页上的相邻两行时,其中一个用户必须等待另一个用户释放锁,这会明显地降低系统的性能。interbase和大多数关系数据库一样,采用的是乐观锁,而且读锁是共享的,写锁是排他的。可以在一个读锁上再放置读锁,但不能再放置写锁;你不能在写锁上再放置任何锁。锁是目前解决多用户并发访问的有效手段。

  死锁:当二或多个工作各自具有某个资源的锁定,但其它工作尝试要锁定此资源,而造成工作永久封锁彼此时,会发生死锁。例如:

1. 事务 A 取得数据列 1 的共享锁定。

2. 事务B 取得数据列 2 的共享锁定。

3. 事务A 现在要求数据列 2 的独占锁定,但会被封锁直到事务B 完成并释出对数据列 2 的共享锁定为止。

4. 事务B 现在要求数据列 1 的独占锁定,但会被封锁直到事务A 完成并释出对数据列 1 的共享锁定为止。

等到事务B 完成后,事务A 才能完成,但事务B 被事务A 封锁了。这个状况也称为「循环相依性」(Cyclic Dependency)。事务A 相依于事务B,并且事务B 也因为相依于事务A 而封闭了这个循环。

例如以下操作就会产生死锁,两个连接互相阻塞对方的update。

连接1:

  begin tran

    select * from customers

    update customers set CompanyName = CompanyName

    waitfor delay ‘00:00:05‘

    select * from Employees

    –因为Employees被连接2锁住了,所以这里会阻塞。

    update Employees set LastName = LastName

  commit tran

连接2:

  begin tran

    select * from Employees

    update Employees set LastName = LastName

    waitfor delay ‘00:00:05‘

    select * from customers

    --因为customers被连接1锁住了,所以这里会阻塞。

    update customers set CompanyName = CompanyName

  commit tran

SQL Server遇到死锁时会自动杀死其中一个事务,而另一个事务会正常结束(提交或回滚)。

SQL Server对杀死的连接返回错误代码是1205,异常提示是:

Your transaction (process ID #52) was deadlocked on {lock | communication buffer | thRead} resources with another process and has been chosen as the deadlock victim. Rerun your transaction.

乐观锁、悲观琐、死锁的区别,布布扣,bubuko.com

时间: 2024-12-24 03:50:03

乐观锁、悲观琐、死锁的区别的相关文章

【多线程】公平锁/非公平锁、乐观锁/悲观锁

公平锁/非公平锁(多线程执行顺序的维度) 概念理解 公平锁:加锁前先查看是否有排队等待的线程,有的话优先处理排在前面的线程,先来先得. 非公平所:线程加锁时直接尝试获取锁,获取不到就自动到队尾等待. 例子 ReentrantLock 同时支持两种锁 //创建一个非公平锁,默认是非公平锁 Lock nonFairLock= new ReentrantLock(); Lock nonFairLock= new ReentrantLock(false); //创建一个公平锁,构造传参true Lock

AtomicInteger如何保证线程安全以及乐观锁/悲观锁的概念

众所周知,JDK提供了AtomicInteger保证对数字的操作是线程安全的,线程安全我首先想到了synchronized和Lock,但是这种方式又有一个名字,叫做互斥锁,一次只能有一个持有锁的线程进入,再加上还有不同线程争夺锁这个机制,效率比较低,所以又称“悲观锁”. 但是相应的有了乐观锁的概念,他的思路就是,它不加锁去完成某项操作,如果因为冲突失败就重试,直到成功为止.这种说的比较抽象,我们直接拿AtomicInteger源码举例,因为AtomicInteger保证线程安全就是因为使用了乐观

[转]数据库并发控制 乐观锁,悲观锁

在数据库中,并发控制有乐观锁和悲观锁之间,什么时候用乐观锁比较好什么时候用悲观锁比较好? 实际生产环境里边,如果并发量不大,完全可以使用悲观锁定的方法,这种方法使用起来非常方便和简单.但是如果系统的并发非常大的话,悲观锁定会带来非常大的性能问题,所以就要选择乐观锁定的方法. 悲观锁假定其他用户企图访问或者改变你正在访问.更改的对象的概率是很高的,因此在悲观锁的环境中,在你开始改变此对象之前就将该对象锁住,并且直到你提交了所作的更改之后才释放锁.悲观的缺陷是不论是页锁还是行锁,加锁的时间可能会很长

最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 01.乐观锁 vs 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度,在Java和数据库中都有此概念对应的实际应用. 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制. 乐观锁适用于多

Mysql:行锁 表锁 乐观锁 悲观锁 读锁 写锁

锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足.在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM引擎)和页级锁(BDB引擎 ). 行锁 锁定整个行数据,开销大,加锁慢,会出现死锁.锁定粒度小,发生锁冲突的概率低,并发度高. 表锁 锁定整个表数据,开销小,加锁快,不会出现死锁.锁定粒度大,发生锁冲突概率高,并发度低. 悲观锁 每次取数据时都认为别人会修改,所以每次取数据的时候都会上锁,这样别人想拿这个数据就会被阻

Mysql锁机制--乐观锁 & 悲观锁

前言 mysql的并发操作时而引起的数据的不一致性(数据冲突): 丢失更新:两个用户(或以上)对同一个数据对象操作引起的数据丢失. 解决方案:1.悲观锁,假设丢失更新一定存在:sql后面加上for update:这是数据库的一种机制. 2.乐观锁,假设丢失更新不一定发生.update时候存在版本,更新时候按版本号进行更新. 第一部分 悲观锁 1 概念 悲观锁,正如其名,它指的是对数据被外界(包括当前系统的其它事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于

共享锁&排它锁 || 乐观锁&悲观索

1.共享锁只用于表级,排他锁用于行级. 2.加了共享锁的对象,可以继续加共享锁,不能再加排他锁.加了排他锁后,不能再加任何锁. 3.比如一个DML操作,就要对受影响的行加排他锁,这样就不允许再加别的锁,也就是说别的会话不能修改这些行.同时为了避免在做这个DML操作的时候,有别的会话执行DDL,修改表的定义,所以要在表上加共享锁,这样就阻止了DDL的操作. 4.当执行DDL操作时,就需要在全表上加排他锁 为什么需要锁(并发控制)? 在多用户环境中,在同一时间可能会有多个用户更新相同的记录,这会产生

并发控制:(二)乐观锁 悲观锁

悲观锁:(pessimistic locking):假定:发生冲突的概率比较高,实现:在对任意记录进行修改前,先尝试为该记录加上排他锁(exclusive locking).这样其他事务如果想操作该记录,需要等待锁的释放特点: 当并发量较大,频繁访问时,等待时间较长,并发访问性不好例如: java的synchronized,SqlServer页级锁,Oracle行级锁 乐观锁:(optimistic locking)假设:发生冲突的概率比较低实现:在提交对记录的更改时才将对象锁住,提交前需要检查

乐观锁悲观锁

老生常谈,这个写的挺好. http://blog.csdn.net/hongchangfirst/article/details/26004335 悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁.传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁. 乐观锁(Optimistic Lock), 顾名思义,就是很乐观

乐观锁+悲观锁

乐观锁: 乐观锁( Optimistic Locking ) 相对悲观锁而言,乐观锁机制采取了更加宽松的加锁机制.悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性.但随之而来的就是数据库性能的大量开销,特别是对长事务而 言,这样的开销往往无法承受.而乐观锁机制在一定程度上解决了这个问题.乐观锁,大多是基于数据版本( Version )记录机制实现.何谓数据版本?即为数据增加一个版本标识,在基于数据库表的版本解决方案中,一般是通过为数据库表增加一个 “version” 字段来实