MySQL 有哪些锁?
当会话退出后,会释放所有锁
这是因为申请 MDL 锁的操作会形成一个队列,队列中写锁获取优先级高于读锁,一旦出现 MDL 写锁等待,会阻塞后续该表的所有 CRUD 操作。 如果一个写锁在队列中,可能会阻塞队列中的后续操作,导致问题
共享锁(S 锁)满足读读共享,读写互斥。独占锁(X 锁)满足写写互斥、读写互斥。
MySQL 加锁时,是先生成锁结构,然后设置锁的状态,如果锁状态是等待状态,并不是意味着事务成功获取到了锁,只有当锁状态为正常状态时,才代表事务成功获取到了锁
全局锁
锁住整个数据库,只读状态
- 上锁
flush tables with read lock - 释放
unlock tables(会话断开,全局锁自动释放) - 主要应用于做全库逻辑备份,但是成本很高,可以通过可重复度的MVCC进行备份
- 备份数据库的工具是 mysqldump,在使用 mysqldump 时加上
–single-transaction参数的时候,就会在备份数据库之前先开启事务。这种方法只适用于支持「可重复读隔离级别的事务」的存储引擎。
表级锁
- 共享锁不能升级为独占锁,因为如果多个线程都获取了共享锁,都想升级,都需要其他线程释放共享锁,导致死锁
- 加了共享锁,所有线程都不能写,包括当前线程(上面的原因)
表锁
- 加锁锁:
- 共享锁:
lock tables t_student read; - 独占锁:
lock tables t_student write;
- 共享锁:
- 释放锁:
unlock tables:释放当前会话所有表锁
元数据锁
- 非显示使用
- 对一张表进行 CRUD 操作时,加的是 MDL 读锁;
- 对一张表做结构变更操作的时候,加的是 MDL 写锁;
- MDL 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更。
- 事物执行期间,MDL一直持有
意向锁
加锁前,会加上对应的意向锁
- 插入、更新、删除加意向独占锁
- 查询加对应的锁
- 独占查询加意向独占锁
- 共享查询加意向共享锁
- 目的时为了快速判断表里是否有记录被加锁
- 如果有行共享锁,加上意向共享锁后有想要加行独占锁的就会立刻知道,不需要遍历其他行
- 行独占锁也一样
- 如果加了意向共享锁,再进行表独占锁获取也会阻塞
AUTO-INC 锁
- 是在执行完插入语句后就会立即释放,而不是事务提交后释放
- 一个事务在持有 AUTO-INC 锁的过程中,其他的事务如果要向该表插入语句都会被阻塞,从而保证插入数据时,被
AUTO_INCREMENT修饰的字段的值是连续递增的。 - InnoDB 存储引擎提供了个 innodb_autoinc_lock_mode 的系统变量,是用来控制选择用 AUTO-INC 锁,还是轻量级的锁。
- 当 innodb_autoinc_lock_mode = 0,就采用 AUTO-INC 锁,语句执行结束后才释放锁;
- 当插入操作很大的时候,性能会比较差,其他插入操作都在等待
- 当 innodb_autoinc_lock_mode = 2,就采用轻量级锁,申请自增主键后就释放锁,并不需要等语句执行后才释放。
- 当搭配 binlog 的日志格式是 statement 一起使用的时候,在「主从复制的场景」中会发生数据不一致的问题。
- 如果几个多行插入的操作时,可能并不是交替插入,如果binlog记录原始语句,可能插入顺序不一致,可以通过binlog日志设置为row避免
- 当 innodb_autoinc_lock_mode = 1: - 普通 insert 语句,自增锁在申请之后就马上释放; - 类似 insert …… select 这样的批量插入数据的语句,自增锁还是要等语句结束后才被释放;
- 当 innodb_autoinc_lock_mode = 0,就采用 AUTO-INC 锁,语句执行结束后才释放锁;
行级锁
InnoDB 引擎支持, MyISAM 引擎不支持。
- 加锁:
- 共享锁:
select ... lock in share mode;不加lock in share mode的select无锁 - 独占锁:
- 查询:
select ... for update; - 任何类型的修改、删除
- 查询:
- 共享锁:
- 释放:
- 提交事务即可
行级锁的类型主要有三类:
- Record Lock,记录锁,也就是仅仅把一条记录锁上;
- 区分共享和独占锁
- Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身;
- 只存在可重复读级别
- 不区分共享和独占锁,两者没差别,可以都看成共享锁
- Next-Key Lock:临键锁,Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。
- 因为有记录锁,所以区分共享和独占锁
- 插入意向锁:如果执行插入操作,插入位置有间隙锁,会生成插入意向锁
- 是一种特殊的间隙锁,不是锁区见,而是锁一个点(但是是不存在记录的点)
- 但是和间隙锁互斥
- 记录锁锁有记录的部分,间隙锁和插入意向锁锁没有记录的部分
