分类:
在MySQL中按照锁的粒度,可将锁分为全局锁,表级锁,行级锁。
全局锁:针对某一数据库加的锁。
表级锁:针对某一张表加的锁。
行级锁:针对某一张表中的某一行加锁。
先附上一张思维导图,对MySQL中锁的分类加以概括:
接下来将逐一介绍MySQL锁体系中的锁。
全局锁:
当我们给某个数据库加上全局锁,在持有锁的过程中,允许对该库的所有表进行查,但是其他的增加,删除,修改操作都将处于阻塞状态。这样做的目的是保证数据的一致性,完整性。典型应用是在数据库备份。
-- 给数据库加锁
flush tables with read lock;
-- 执行数据库备份操作,直接在window命令执行
mysqldump -uroot -p_____ 数据库名 存储位置;
-- 释放锁
unlock tables;
以上是对全局锁的应用。但在实际开发中我们的数据库不可能部署在一台机器上,会采用主从部署,这样就会存在问题 :
如果从主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆。
如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制文件(binlog),从导致主从延迟。
那么此时我们可以在备份语句后加--single-transcation参数来完成不加锁的一致性数据库备份。加上--single-transcation实际上就是拉取某一时刻的快照,然后将其备份。
表级锁:
分类:
可以将表级锁分为:
- 表锁
- 元数据锁(meta data lock,MDL)
- 意向锁
表锁:
表锁又可以分为:
- 表共享读锁:当前客户端可读,不可写,其他客户端可读,写阻塞
- 表独占写锁:当前客户端可读可写,其他客户端读写阻塞
-- 加锁
lock tables 表名 read/write;
-- 解锁
unlock tables;
元数据锁:
元数据说白了就是维护表结构的一张表。设立元数据锁为了防止DDL与DML的冲突,保证读写的正确性。元数据锁加锁过程是系统自动控制,无需显示使用,在访问一张表时候自动加上。
当读数据时,加上SHARED_READ锁,此时其他事务可以修改。在执行修改时,加上SHARED_WRITE锁,此时读可以操作。但是不可以修改表结构。EXCLUSIVE与其他锁都互斥。
意向锁:
我们可以想以下这样的操作,在加表锁之前需要检查行记录是否加锁,如果有加锁就需要等待锁释放以后再进行表锁的后续操作。此时检查行锁的操作,就需要从表的第一行向下逐一进行,直到最后一行记录。这样的话效率会表较低,因此引入了意向锁。
意向锁解决表锁和行锁的冲突问题,减少了表锁的检查。
- 意向共享锁(IS):由语句select---lock in share mode添加 ,与表锁排他锁(write)互斥。
- 意向排他锁(IX):由insert,update,delete,select--for update添加,与表锁read,write都互斥。
- 意向锁之间不互斥。
行级锁:
注意:InnoDB的数据时基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。
行级锁可以分为:
- 行锁:锁定单个记录的锁,防止其他事务对此行进行update和delete。在RC RR隔离级别下支持。
- 间隙锁:锁定索引记录的间隙,不含该记录,确保索引间隙不变,防止其他事务进行insert,产生幻读。在RR(可重复读)隔离级别下都支持。
- 临键锁:行锁和间隙锁的组合,同时锁住数据,并锁住数据前的间隙。在RR隔离级别下支持。
行锁:
共享锁:允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。
排他锁:允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。
当前锁类型 \ 请求锁类型 | S(共享锁) | X(排他锁) |
S(共享锁) | 兼容 | 冲突 |
X(排他锁) | 冲突 | 冲突 |
在执行INSERT UPDATE DELETE SELECT...FOR UPDATE的时候加的是排他锁。
在执行SELECT ... LOCK IN SHARE MODE加的是共享锁。
SQL | 行锁类型 | 说明 |
INSERT | 排他锁 | 自动加锁 |
UPDATE | 排他锁 | 自动加锁 |
DELETE | 排他锁 | 自动加锁 |
SELECT | 不加锁 | |
SELECT...LOCK IN SHARE MODE | 共享锁 | 手动加上LOCK IN SHARE MODE |
SELECT...FOR UPDATE | 排他锁 | 手动加上FOR UPDATE |
注意:InnoDB的行锁是针对索引加的锁,不通过索引条件检索数据,那么InnoDB将表中的所有记录加锁,升级为表锁。
间隙锁/临键锁:
间隙锁只对记录之间间隙锁住,而临键锁对记录和间隙加锁。
间隙锁
间隙锁只对记录之间的间隙锁住,触发条件是当进行范围查询时未命中记录,查询条件必须命中索引,间隙锁只会出现在RR事务级别中,是为了防止幻读的产生。遵循左开右闭。
临键锁:
临键锁将查询出来的记录锁住,同时把该记录之间的间隙以及相邻的下一个区间也锁住。
触发条件是:范围查询并命中,查询命中了索引。
作用:避免了在范围查询时出现脏读,出复读,幻读等问题。加上临建锁之后,范围查询区间不允许数据的修改和插入。