MySQL 中的锁
全局锁
全局锁是将整个数据库都锁上,一般用于备份数据库。整张表都属于只读状态。如果支持可重复读的级别,可以在备份之前生成一份 ReadView,用这个 ReadView。
表级锁
表锁
表锁有读锁和写锁,读锁就是让这张表大家都可以读,但是没有人可以写。写锁就是只有当前这个线程可以读或写,别的线程读和写都不行。表锁除了锁住了表,其实也把自己线程给锁住了。比如执行 lock tables t1 read, t2 write 这条语句,当前线程在解锁之前只能读表 t1,写表 t2,不允许做其他操作。
元数据锁
元数据锁也称 MDL 锁,我们不需要显式地调用 MDL 锁,因为操作数据库的时候会自动加上 MDL 锁。MDL 锁分为读锁和写锁。MDL 读锁就是在增删改查的时候,不允许其他线程读。MDL 写锁就是在对表进行修改时,不允许其他线程读。

由于 MDL 锁存在写优先级 且有队列等待机制,一个长事务可能会拖死整个数据库:
事务 A:开启长事务,做了一个慢查询(持有 MDL 读锁)。
事务 B:想改字段名(申请 MDL 写锁),因为 A 没结束,B 只能排队。
后续所有请求 :新的 SELECT 请求虽然也是读锁,但因为 B 在排队且优先级高,导致后面所有的请求全都在 B 后面排队。
后果:数据库连接数瞬间爆满,整个系统瘫痪
意向锁
这是 InnoDB 引擎为了让表锁和行锁共存而设计的一种"旗语"。当你想给某一行加锁时,InnoDB 会自动先给表加一个意向锁:
意向共享锁 (IS):打算给行加 S 锁。
意向排他锁 (IX):打算给行加 X 锁。
它的意义在于:如果有人想给整张表加"写锁",他不需要去逐行检查有没有行锁,只需要看一眼表上有没有"意向锁"的标志位即可。
AUTO-INC 锁
Auto-Inc 锁是用来保证生成的主键严格自增的。它并不在整个事务期间都上锁,而是执行完插入语句之后就会立刻释放锁。

由于AUTO-INC 锁会等到所有数据都插入完成之后才释放锁,如果有大量数据插入速度会很慢,所以 InnoDB 提供了一种轻量级的互斥锁。
轻量级互斥量(Mutex)不再锁定整张表,它只锁定**"自增计数器"这个数字本身**。
执行逻辑:
申请:事务 A 说"我要 5 个 ID"。
获取:它迅速去访问内存中的计数器(通过 Mutex 保证同一时刻只有一个线程在拨动数字)。
分配:计数器从 100 变成 105,把 101-105 分给事务 A。
释放:重点来了! 只要 A 拿到了这组数字,Mutex 就会立刻释放,不需要等待 A 的插入操作完成。
行级锁

Record Lock
RecordLock 锁的是单独的一条记录。
Gap Lock
幻读就是读了两次数据库,前后数据多了或者少了。 MySQL 中解决幻读的方法有两个:第一个是通过 MVCC 的快照机制,采用可重复读级别,在事务开始前获得一个快照,后面一直用这个快照。第二个是通过Next-key lock,让你根本没办法插进去新的数据。
Next-key Lock

插入意向锁
前面的意向锁,你要插入一行,意向锁会对这个表做标记,告诉数据库这个表现在有人在用,就不需要一行行地去扫描了。插入意向锁不是意向锁。下面是一个例子。
