mysql锁可以按模式分类:乐观锁与悲观锁。按粒度可以分为全局锁,表级锁,页级锁,行级锁。按照属性可以分为共享锁,排他锁。按状态分为意向共享锁,意向排他锁。按算法分为:间隙锁,临键锁,记录锁。
全局锁,表级锁,页级锁,行级锁
全局锁
全局锁就是对整个数据库实例加锁。
表级锁
当前操作的整张表加锁。
mysql里面表级别的锁有两种:一种是表锁,一种是元数据锁(MDL,在对表结构做变更的时候需要获得MDL写锁)
元数据锁:MDL 不需要显式使用,在访问一个表的时候会被自动加上,在 MySQL 5.5 版本中引入了 MDL,当对一个表做增删改查操作的时候,加 MDL读锁;当要对表做结构变更操作的时候,加 MDL 写锁。
页级别锁
页级别锁是mysql中锁粒度介于行级别锁和表级锁中的一种锁。表级锁速度快,但冲突多,行级锁冲突少,但是速度慢。因此,采取了一种折中的页级锁,一次锁定相邻的一组记录。
行级锁
行级锁是粒度最低的锁,发生锁冲突的概率也最低,并发度最高。但是加锁慢,开销大,容易发生死锁。
mysql中只有InnoDB支持行级锁,行级锁分为共享锁和排他锁
在mysql中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种。如果一条sql语句操作了主键索引,mysql就会锁定这条主键索引。如果一条语句操作了非主键索引,mysql会先锁定该非主键索引,再锁定相关的主键索引。在update,delete操作的时候,mysql不仅锁定where条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的next-key locking
乐观锁与悲观锁
乐观锁
乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回给用户错误的信息,让用户决定如何去做。
一般使用版本机制来实现乐观锁
悲观锁
悲观锁,正如其名,具有强烈的独占和排他特性,每次去拿数据的时候都认为别人会修改,在整个数据处理过程中,将数据处于锁定的状态。共享锁和排他锁是悲观锁的不同实现,他两都属于悲观锁的范畴。
注意:mysql InnoDB默认行级锁,行级锁都是基于索引的,如果一条sql语句用不到索引是不会使用行级锁的,会使用表级锁把整张表锁住。
共享锁和排他锁
共享锁
共享锁,又称之为读锁,S锁。当事务A对数据加上读锁后,其他事务只能对该数据加读锁,不能做任何修改操作,也就是不能添加写锁。只有当事务A上的读锁被释放后,其他事务才能对其添加写锁。
共享锁(S锁)主要是为了支持并发的读取数据而出现的,读取数据时,不允许其他事务对当前数据进行修改操作,从而避免“不可重复读”的问题的出现。
排他锁
排他锁,又称之为写锁,X锁。当事务对数据加上写锁后,其他事务即不能对该数据添加读锁,也不能对该数据添加写锁,写锁与其他锁都是互斥的。
mysql InnoDB引擎默认update,delete,insert 都会自动给涉及到的数据加上排他锁,select 语句默认不会加任何锁类型。
意向共享锁和意向排他锁
意向锁是表锁,为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁共存。
当事务A有行锁时,mysql会自动为该表添加意向锁,事务B如果想申请整个表的写锁,那么不需要遍历每一行判断是否存在行锁,而直接判断是否存在意向锁,增加性能。
间隙锁,临键锁,记录锁
记录锁,间隙锁,临键锁都是排他锁,而记录锁的使用方法跟排他锁介绍一致。
https://juejin.cn/post/6931752749545553933