1. 全局锁
- 对整个数据库进行加锁
- MySQL加全局读锁的命令是 Flush tables with read lock
- 使用场景是全库逻辑备份。就是把整个库每个表都select出来存成文本
- 让整个库只读,会出现以下问题
- 在主库备份,则备份期间不能执行更新,业务基本要停止
- 若在从库备份,则备份期间从库不能执行主库同步过来的binlog,会导致主从延迟
2. 表级锁
- 语法是 lock tables ... read/write。 可以用unlock tables主动释放锁
- 开销小,加锁快,但锁粒度大,并发量低
- 元数据锁(meta data lock,MDL):MDL加锁过程是系统自动控制的,无序显示调用,在访问一张表时会自动加上。
- MDL锁主要作用是维护表元数据的数据一致性,在表上有活动事务时,不可以对元数据进行写入操作。避免DML和DDL冲突,保证读写的正确性
- 当对一张表进行增删改查时,加MDL读锁
- 当对一张表结构进行变更操作时,加MDL写锁
3. 行级锁(InnoDB存储引擎才支持)
- 开销大,加锁慢,会出现死锁
- 但是发生锁冲突概率小,并发量比较高
- InnoDB支持行锁。行锁是针对索引加的锁,如果更新不走索引,则加表锁
- 在InnoDB事务中,行锁是在需要的时候才加上,但并不是不需要了就立刻释放,而是要等到事务结束才释放,这就是两阶段锁协议
- 行级锁包括了共享锁(s锁)、排它锁(x锁)
- 对于增删改语句,InnoDB会自动给涉及的数据集加排它锁(x)
- 对于普通select语句,InnoDB不会加任何锁
- 可以通过一下语句显示给查询语句加共享锁或排它锁
- select * from user where ... lock in share mode
- select * from user where ... for update (加排它锁)
4. 意向锁(InnoDB存储引擎才支持)
- 意向锁也分为共享/排他两种
- InnoDB允许行级锁与表级锁共存,而意向锁就是表锁(但它并不是真的加了表锁)
为什么需要意向锁
- 假设事务A获取了某一行的排它锁,尚未提交,此时事务B想要获取表锁,则必须确认表中的每一行都不存在排它锁,很明显这样一行行检查效率会很低,所以引入了意向锁
- 引入意向锁之后,如果事务A对每一行加了排它锁,实际上是此表上会存在两种锁,表中某一行的排它锁和表上的意向排它锁;如果事务B此时再企图再该表上加锁时,则会看见表上有一个意向排它锁,则会直接阻塞这个企图加锁过程。这样不用检查表中的每一行是否加了锁,只需要检查表上的意向锁。
各种锁的兼容性如下
兼容性 | IS | IX | S | X |
IS | Y | Y | Y | N |
IX | Y | Y | N | N |
S | Y | N | Y | N |
X | N | N | N | N |
- 这里都是指的是表锁,比如,当表上有意向共享锁,此时还可以在表上加意向共享锁、意向排它锁、读锁。
- 意向锁是InnoDB自己维护,我们不需要手动加。
.