Skip to content

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 引擎支持, 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 的组合,锁定一个范围,并且锁定记录本身。
    • 因为有记录锁,所以区分共享和独占锁
  • 插入意向锁:如果执行插入操作,插入位置有间隙锁,会生成插入意向锁
    • 是一种特殊的间隙锁,不是锁区见,而是锁一个点(但是是不存在记录的点)
    • 但是和间隙锁互斥
  • 记录锁锁有记录的部分,间隙锁和插入意向锁锁没有记录的部分

正在精进