MySQL中的锁按照锁的粒度来分,以下三种:
全局锁:锁定数据库的全部表
表级锁:每次操作锁定整张表
行级锁:每次操作锁定表中的一条数据
1.全局锁
全局锁就是对整个数据库实例加锁,加锁后的整个示例就处于只读状态,后续的DML、DDL语句,已经更新操作的事务提交语句都将被阻塞。
典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
特点:
数据库中加全局锁,是一个比较重的操作,存在以下问题:
1.如果是在主库上备份,那么在备份期间都不能执行更新,业务基本上进行停摆。
2.如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制文件(binlog),会导致主从延迟。
在InnoDB引擎上,我们可以在备份时添加上参数 --single-transaction参数来完成不加锁的一致性数据备份。
2.表级锁
表级锁,每次操作锁住整张表。锁定粒度大,发生所冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中。
对于表级锁,分为以下三类:
1.表锁
2.元数据锁(meta data lock,MDL)
3.意向锁
2.1表锁
对于表锁,分为两类
1.表共享读锁(read lock):所有客户端都只能读,不能写。
2.表独占写锁(write lock):当前客户端能读能写,其他客户端既不能读也不能写。
语法:
1.加锁:lock tables 表名 ... read/write
2.释放锁:unlock tables
2.2元数据锁(MDL)
元数据是描述数据库的数据结构及其属性的信息,包括表、列、索引、触发器等对象的定义和属性。
MDL 加锁过程时系统自动控制,无需显示使用,在访问一张表的时候会自动加上。MDL 锁主要作用是维护表元数据的数据一致性,在表上有活动事务的时候,不可以对元数据进行写入操作。为了避免 DML 与 DDL 冲突,保证读写的正确性。
在 MySQL5.5 中引入了 MDL,当对一张表进行增删改查的时候,加 MDL 读锁(共享);当对表结构进行变更操作的时候,加 MDL 写锁(排他)。
2.3意向锁
当客户端A需要对表中的一条数据更新时,首先会开启一个事务,在执行更新操作时会给这一行数据加上行锁,在事务还未提交时,客户端B要操作这张表,开启一个事务后,操作时需要给这张表加表锁。加表锁的过程,需要对表中的记录依次进行检查看是否加了行锁,如果有行锁,那加表锁的操作会被阻塞,直到行锁释放。
而对表中的记录依次检查比较耗费性能和时间,所以引入了意向锁,使得表锁不用检查每一条数据是否加了行锁,只需查看意向锁。
意向锁有两种:
1- 意向共享锁(IS):由语句 select … lock in share mode 添加。与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。
2- 意向排他锁(IX):由 insert、update、delete、select … for update 添加。与表锁共享锁(read)及排他锁(write)都互斥。意向锁之间不会互斥。
3行级锁
行级锁,每次操作锁住对应的行数据,锁定粒度最小,发生锁冲突的概率最低,并发度最高,应用在InnoDB引擎中。
InnoDB的数据是基于索引组织的(聚集索引的叶子节点存储相应的行数据),行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。对于行级锁,主要分为以下三类:
1.行锁(Recore Lock):锁定单个行记录的锁,防止其他事务对此进行update和delete。在RC、RR隔离级别下都支持。
2.间隙锁(Gap Lock):锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。
3.临键锁(Next-Key Lock):行锁与间隙锁组合,同时锁住数据,并锁住数据前的间隙Gap。在RR隔离级别支持。
3.1行锁
InnoDB引擎实现了以下两种类型的行锁:
1.共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
2.排他锁(X):允许获取排他锁的事务更新数据,组织其他事务获得相同数据集的共享锁和排他锁。
S(共享锁) | X(排他锁) | |
S(共享锁) | 兼容 | 冲突 |
X(排他锁) | 冲突 | 冲突 |
行锁-演示
默认情况下,InnoDB引擎在REPEATABLE READ事务隔离级别下,InnoDB使用next-key锁进行搜索和索引扫描,以防止幻读。
1.针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
2.InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁。
3.2间隙锁
索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁
间隙锁(Gap lock)是MySQL数据库中一种用于处理并发事务的锁机制。它的目的是在事务中保护数据的一致性和完整性。
间隙锁的主要作用是锁定一段数据范围之间的间隙,即锁定两个值之间的空隙。当一个事务对数据范围中的某个数据行进行锁定时,间隙锁会阻止其他事务在这个数据范围内插入新的数据行。这样可以确保在事务修改数据时,其他事务不会在相同的数据范围内插入新的数据,从而保持数据的一致性。
3.3临键锁(next-key lock)
Next-Key Lock是MySQL数据库中InnoDB存储引擎的一种锁机制,用于解决事务并发控制中的幻读问题。Next-Key Lock是一种结合了记录锁(Record Lock)和间隙锁(Gap Lock)的锁定技术。
防止幻读:在事务隔离级别为可重复读(REPEATABLE READ)时,Next-Key Lock可以防止幻读现象。幻读是指在同一个事务中,连续执行两次相同的查询,可能导致第二次查询看到第一次查询未看到的行。
保证数据的一致性:通过锁定记录及其前面的间隙,Next-Key Lock确保了在事务执行过程中,其他事务无法插入符合条件的记录,从而保证了数据的一致性。
临键锁锁住的区间为记录+区间(左开右闭) ,InnoDB中行级锁是基于索引实现的,临键锁只与非唯一索引有关,在唯一索引列(包括主键列)是不存在临键锁的。