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

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

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

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

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

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 而封闭了这个循环。it

例如如下操做就会产生死锁,两个链接互相阻塞对方的update。io

链接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.

相关文章
相关标签/搜索