目录
概述:
锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/0)的争用以外,数据也是-种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。
MySQL中的锁,按照锁的粒度分,分为以下三类:
1. 全局锁——锁定数据库中的所有表。
2. 表级锁——每次操作锁住整张表。
3. 行级锁——每次操作锁住对应 的行数据
全局锁
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。
其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性
全库逻辑备份不加锁的情况
主要是由于并发操作导致的数据不一致性,在备份间隙对记录好的数据进行修改,导致实际数据和记录数据不一致
全库逻辑备份加锁的情况
进行全局锁操作后是进入了只读状态,并不是所有SQL语句都不生效
弊端
数据库中加全局锁,是一个比较重的操作,存在以下问题:
1. 如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆
2. 如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志 (binlog),会导致主从延迟
表级锁
表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用MyISAM、InnODB、BDB等存储引擎中。
对于表级锁,主要分为以下三类:
1.表锁
2.元数据锁
3.意向锁
表锁
对于表锁,分为两类:
1.表共享读锁 (read lock)
2.表独占写锁 (write lock)
语法
加锁—— lock tables 表名... read / write
释放锁—— unlock tables / 客户端断开连接
锁特性
表共享读锁——加锁的用户和其他用户都只能对该表进行DQL操作,都不能进行DML操作
表独占写锁——加锁的用户能对该表进行任意操作,而其他用户什么操作都不能有
元数据锁
元数据锁是在执行 DDL操作时由数据库自动加入的,并且会一直保持锁状态,直到操作完成才会自动释放。这种锁可以保证在 DDL 操作期间表结构的一致性和完整性
意向锁
为了避免DML在执行时,加的行锁与表锁的冲突(因为表锁和行锁有可能不能兼容),在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。
不加意向锁,加表锁前会对整张表每一行都进行遍历来确定行锁的存在,这样子就很麻烦,而意向锁的存在就类似于所有行锁的大家长,加表锁前直接问一下这个大家长的意见,家长同意(锁兼容)就可以直接加,不同意(锁不兼容)就被阻塞,直到行锁释放
语法
兼容性 ![](https://img-blog.csdnimg.cn/41ce5fe8622144b29718fb5b673b5eaf.png)
行级锁
行级锁是正对索引加的锁,不是针对记录加的锁,对于DML操作,InnoDB 存储引擎采用的是行级锁。当事务对某一行进行插入、删除或更新时,只有该行被锁定,其他行依然可以被其他事务访问。这种锁可以提高并发性,避免不必要的资源浪费,但也需要进行合理安排以防止产生死锁等问题。
意思就是说,如果执行 DML 操作你修改的字段是加了索引的,那么你修改该字段所在的行就会被上锁。如果该字段不是添加了索引的,或者索引失效了的,那么你对该行进行修改操作的时候。他锁住的就不是这一行,而是整张表,就会导致效率下降。
行锁
分类
共享锁和共享锁之间是兼容的,共享锁和排他锁间是互斥的
常见CRUD操作的行锁类型
间隙锁
在Mysql中,间隙锁(Gap Lock)是一种锁策略,用于解决并发操作下多个会话同时访问同一个范围的非唯一索引时可能出现的幻读问题。
案例理解
通过生活案例来说明这个问题。假设你在超市购买商品时,需要先到货架上查找所需商品以及对应的价格等信息,此过程与Mysql查询非常相似。当超市进货员为货架添加或移除商品时,就产生了“间隙” - 这些空缺位置还未被新的商品填充。
现在,如果另外一个顾客也在这个时间段内想要去查询相同品种的商品信息,他会发现目标商品原本存在的位置已经没有了,即使服务器暂时无法立即还原该位置,也不能让其他人占据该间隙或将其他的商品插入他们的间隙中,否则在付款结账时这些商品数据就会与实际不符合,很可能导致计算错误。
同样,在数据库中,一个会话正在检索一定范围内的数据时,如果其他会话在这个时间点修改了这个范围内的数据,那么返回的结果集就可能包含在事务开始时不存在但在事务结束时存在的行 - 即所谓的“幻读”。
因此,间隙锁就是为了解决这个问题而诞生的,它为范围进行了一定程度的“保护”,使得当其他会话尝试插入包含这个范围中的任何记录时,都必须等待当前锁已经释放后才能继续进行操作。
间隙锁通常出现在可重复读和序列化隔离级别下,在执行区间查询或点查询时可能产生。
代码理解![](https://img-blog.csdnimg.cn/b11a258d1e1a44cca82040d86e491b6b.png)
临键锁
行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下支持。
总结: