加锁范围分类
全局锁
表锁
表锁 -- innodb下一般不会直接使用表锁(lock table)
元数据锁(MDL)
行锁
全局锁
全局锁就是对整个数据库实例加锁。MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。
全局锁的典型使用场景是,做全库逻辑备份。当然若是innodb引擎的话,可直接使用可重复读的事务隔离级别就可避免使用全局锁,而如果使用的是myisam引擎的话则只能使用全局锁来保证数据一致性.
MDL(metadata lock)
MDL的作用是保证读写的正确性.MDL 不需要显式使用,在访问一个表的时候会被自动加上。当对一个表做增删改查操作的时候,加 MDL 读锁;当要对表做结构变更操作的时候,加 MDL 写锁。
MDL的释放时机是事务提交的时候.
Online DDL
online ddl主要包括3个阶段,prepare阶段,ddl执行阶段,commit阶段.
Online DDL的过程是这样的:
拿MDL写锁
降级成MDL读锁
真正做DDL
升级成MDL写锁
释放MDL锁

行锁
行锁释放锁的时机是在事务提交的时候,所以我们需要将一个事务中最容易造成锁冲突,并发度小的的sql语句放在最后执行.
间隙锁
间隙锁(GAP LOCK),锁的就是两个值之间的空隙。间隙锁跟间隙锁之间不存在冲突,跟间隙锁存在冲突的是往这个间隙中插入记录.
next-key Lock
间隙锁和行锁合称 next-key lock,每个 next-key lock 是前开后闭区间。
死锁
当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。
死锁的解决策略 :
等待超时(默认50s)
检查回滚(默认开启)
一种策略是,直接进入等待,直到超时。这个超时时间可以通过参数 innodb_lock_wait_timeout
来设置。另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数innodb_deadlock_detect
设置为 on,表示开启这个逻辑。
主动检查死锁时,每当一个事务被锁的时候,就要看看它所依赖的线程有没有被别人锁住,如此循环,最后判断是否出现了循环等待,也就是死锁。每个新来的被堵住的线程,都要判断会不会由于自己的加入导致了死锁,这是一个时间复杂度是 O(n) 的操作。假设有 1000 个并发线程要同时更新同一行,那么死锁检测操作就是 100 万这个量级的。虽然最终检测的结果是没有死锁,但是这期间要消耗大量的 CPU 资源。因此,你就会看到 CPU 利用率很高,但是每秒却执行不了几个事务。




