锁是计算机协调多进程或线程并发访问某一资源的机制,数据库中的数据也是一种供多用户共享的资源,需要保证数据并发访问的一致性、有效性。锁冲突也是影响数据库并发访问性能的一个重要因素。
全局锁
全局锁是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML写、DDL和已经更新操作的事务提交语句都会阻塞
应用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性
典型应用是做全库的逻辑备份,保证获取一致性视图
添加全局锁:flush tables with read lock;
特点:
- 主库上备份,备份期间不能更新,业务停摆
- 从库上备份,备份期间不能执行主库同步过来的二进制日志,导致主从延迟
表级锁
每次操作锁住整张表,锁定力度大,发生冲突概率最高,并发度最低
表锁
分为两类:
- 表共享读锁:不会阻塞其他客户端的读,但会阻塞其他客户端的写
- 表独占写锁:阻塞其他客户端的读和写
语法:
加锁:lock tables 表名... read/write;
释放锁:unlock tables
元数据锁
简称MDL,加锁过程是系统自动控制,无需显式调用,在访问一张表的时候会自动加上
主要作用是为了维护数据一致性,避免DML和DDL的冲突
当对一张表进行增删改查时,加MDL读锁(共享),当对表结构进行变更时,加MDL写锁(排他)
意向锁
为了避免DML时行锁与表锁的冲突,意向锁可以减少表锁对行锁的检查
当加行锁时,会给表添加意向锁,接下来加表锁时先判断该表锁是否能与意向锁兼容,若不能则阻塞
分类:
- 意向共享锁(IS):由
SELECT... LOCK I N SHARE MODE添加 - 意向排他锁(IX):由INSERT、UPDATE、DELETE、SELECT FOR UPDATE等添加
行级锁
每次操作锁住对应行数据,发生锁冲突的概率最低,并发度最高,应用于InnoDB引擎中,它是通过对于索引上的索引项加锁实现的
行锁
类型:
- 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁
- 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁
SQL对应加锁的类型:
默认情况下,InnoDB在RR事务隔离下运行,使用next-key锁进行搜索和索引扫描发,防止幻读
- 针对唯一索引检索时,对已存在的记录进行等值匹配时,会自动优化为行锁
- 不通过索引条件检索数据,InnoDB会对表中所有记录加锁,升级为表锁
间隙锁/临键锁
- 索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁
- 索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key退化为间隙锁
- 索引上的范围查询(唯一索引)会访问到不满足条件的第一个值为止
间隙锁唯一目的是防止其他事务插入间隙,可以共存
间隙锁锁的是间隙,不包括范围两端
临键锁会锁定当前数据与当前数据前的数据