1.全局锁
全局锁就是对整个数据库的所有表加锁,加锁后整个实例就处于只读的状态。其典型的使用场景就是全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
1.1全局锁的缺点
-
如果在主库上备份,备份期间都不能执行更新,业务就得等待。
-
如果在从库上备份,那么在备份期间从库不能执行主库同步过来的binlog日志,会导致主从数据一致的延迟。
2.表级锁
2.1表锁
1.表共享读锁(read lock)
读锁不会阻塞其他客户端的读,但是会阻塞所有的写操作。
2.表独占写锁(write lock)
写锁既会阻塞其他客户端的读,也会阻塞其他客户端的写。
2.2元数据锁(MDL)
MDL加锁的过程是系统自动控制,无需显式使用。MDL锁的主要作用是维护表结构的正确性。
当对一张表进行增删改查的时候,会自动加MDL共享读写锁;当对表结构进行变更操作的时候,加MDL排他锁。
MDL共享读写锁之间可以互相兼容,但是与MDL排他锁之间互斥。
2.3意向锁
假设这样一种情况,我们先给某一行数据加了行锁,此时要添加表锁时,为了避免锁的冲突,表锁就要检查每行是否加锁,这样性能就比较低。所以我们引入意向锁,使得减少表锁的检查,意向锁是系统控制,不用我们自己去加。
具体的流程就是:当我们开启事务后,给某一行数据加上行锁时,会自动给表添加意向锁。如果还要添加表锁,那么就会看此表锁与意向锁是否兼容。如下:
意向共享锁(IS):与表锁共享锁(read)兼容,与表锁排他锁(write)互斥。
意向排他锁(IX):与表锁共享锁(read)及排他锁(write)都互斥。意向锁之间不会互斥。
2.3.1那么什么时候会加意向锁呢?
3.行级锁
在Innodb引擎中,数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对数据记录加锁。行级锁分为以下三类:
1.行锁:锁定单个行的锁,防止其他的事务对此进行修改或者删除操作。
2.间隙锁:锁定索引记录间隙,不包含该记录,防止其他的事务在这个间隙进行insert语句。
3.临建锁:就是行锁和间隙锁的组合,同时锁住数据,并锁住数据前面的间隙。
3.1行锁
Innodb引擎实现了以下两种类型的行锁:共享锁(S)和排他锁(X)。
注意:Innodb的行锁是针对索引加的锁,如果SQL语句不以索引字段为条件判断,那么Innodb会对表中的所有记录加锁,此时会升级为表锁
3.2间隙锁和临建锁
默认情况下,Innodb在RR事务的隔离级别运行,Innodb使用间隙锁进行搜索和索引扫描,以防止幻读。
-
如果Sql语句的条件判断字段如果为唯一索引,且给不存在的记录加锁时,行锁会优化为间隙锁给前后间隙加锁。例如:
- 如果Sql语句的条件判断字段如果为非唯一索引,给此行数据加锁以及前后的间隙加上锁。例如:
比如执行:SELECT * FROM cum WHERE age = 6 LOCK IN SHARE MODE,那么id为(1,6],[6,10)的数据会加锁。
- 范围查询的Sql语句的条件判断字段如果为唯一索引,会将此行数据和后面的全部间隙加上锁。例如:
比如执行:SELECT * FROM cum WHERE id >= 10 LOCK IN SHARE MODE,那么会将[10,无穷大)加锁。
注意:间隙锁唯一目的是防止其他事务将数据插入间隙。间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。