MySQL中悲观锁和乐观锁究竟是什么?

索引和锁是数据库中的两个核心知识点,隔离级别的实现都是经过锁来完成的按照锁颗粒对锁进行划分 ?程序员

锁用来对数据进行锁定,咱们能够从锁定对象的粒度大小来对锁进行划分,分别为行锁、页锁和表锁。数据库

  • 行锁就是按照行的粒度对数据进行锁定。锁定力度小,发生锁冲突几率低,能够实现的并发度高,可是对于锁的开销比较大,加锁会比较慢,容易出现死锁状况。并发

  • 页锁就是在页的粒度上进行锁定,锁定的数据资源比行锁要多,由于一个页中能够有多个行记录。当咱们使用页锁的时候,会出现数据浪费的现象,但这样的浪费最多也就是一个页上的数据行。页锁的开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度通常。设计

  • 表锁就是对数据表进行锁定,锁定粒度很大,同时发生锁冲突的几率也会较高,数据访问的并发度低。不过好处在于对锁的使用开销小,加锁会很快。3d

还有区锁和数据库锁.对象

 

 

每一个层级的锁数量是有限制的,由于锁会占用内存空间,锁空间的大小是有限的。当某个层级的锁数量超过了这个层级的阈值时,就会进行锁升级。锁升级就是用更大粒度的锁替代多个更小粒度的锁,好比 InnoDB 中行锁升级为表锁,这样作的好处是占用的锁空间下降了,但同时数据的并发度也降低了。blog

 

从数据库管理的角度对锁进行划分索引

共享锁和排它锁事件

  • 共享锁也叫读锁或 S 锁,共享锁锁定的资源能够被其余用户读取,但不能修改。在进行SELECT的时候,会将对象进行共享锁锁定,当数据读取完毕以后,就会释放共享锁,这样就能够保证数据在读取时不被修改。
    事务

  • 排它锁也叫独占锁、写锁或 X 锁。排它锁锁定的数据只容许进行锁定操做的事务使用,其余事务没法对已锁定的数据进行查询或修改。

当咱们对数据进行更新的时候,也就是INSERT、DELETE或者UPDATE的时候,数据库也会自动使用排它锁,防止其余事务对该数据行进行操做。

 

意向锁(Intent Lock),简单来讲就是给更大一级别的空间示意里面是否已经上过锁。

 

从程序员的角度对锁进行划分

乐观锁

乐观锁(Optimistic Locking)认为对同一数据的并发操做不会总发生,属于小几率事件,不用每次都对数据上锁,也就是不采用数据库自身的锁机制,而是经过程序来实现。在程序上,咱们能够采用版本号机制或者时间戳机制实现。

  • 乐观锁的版本号机制

在表中设计一个版本字段 version,第一次读的时候,会获取 version 字段的取值。而后对数据进行更新或删除操做时,会执行UPDATE ... SET version=version+1 WHERE version=version。此时若是已经有事务对这条数据进行了更改,修改就不会成功。

  • 乐观锁的时间戳机制

时间戳和版本号机制同样,也是在更新提交的时候,将当前数据的时间戳和更新以前取得的时间戳进行比较,若是二者一致则更新成功,不然就是版本冲突。

 

悲观锁

悲观锁(Pessimistic Locking)也是一种思想,对数据被其余事务的修改持保守态度,会经过数据库自身的锁机制来实现,从而保证数据操做的排它性。

适用场景

  • 乐观锁适合读操做多的场景,相对来讲写的操做比较少。它的优势在于程序实现,不存在死锁问题,不过适用场景也会相对乐观,由于它阻止不了除了程序之外的数据库操做。

  • 悲观锁适合写操做多的场景,由于写的操做具备排它性。采用悲观锁的方式,能够在数据库层面阻止其余事务对该数据的操做权限,防止读 - 写和写 - 写的冲突。

总结

乐观锁和悲观锁并非锁,而是锁的设计思想。

避免死锁的发生:

    • 若是事务涉及多个表,操做比较复杂,那么能够尽可能一次锁定全部的资源,而不是逐步来获取,这样能够减小死锁发生的几率;

    • 若是事务须要更新数据表中的大部分数据,数据表又比较大,这时能够采用锁升级的方式,好比将行级锁升级为表级锁,从而减小死锁产生的几率;

    • 不一样事务并发读写多张数据表,能够约定访问表的顺序,采用相同的顺序下降死锁发生的几率。

相关文章
相关标签/搜索