MySQL学习笔记6【锁】

115 阅读3分钟

MySQL学习笔记



1. 全局锁

  • 语法
FLUSH TABLES WITH READ LOCK #加锁

UNLOCK TABLES; 	#解锁

全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。 其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。

  • 问题

    • 如果在主库上进行备份,备份期间无法执行写入操作,导致业务停摆

    • 如果在从库上进行备份,则在备份期间无法执行主库传递过来的二进制日志,导致主从延迟。

    • 在InnoDB引擎中可以加上--single-transaction参数来解决

    mysqldump --single-transaction -uroot -p123456 itcast>itcast.sql

2. 表级锁

  • 语法
LOCK TABLES [表名] READ/WRITE;

UNLOCK TABLES;/与客户端断开连接
  • 表共享读锁(READ)
    • 所有客户端,包括自己无法进行写入操作,但都可以进行读取。
  • 表独占写锁(WRITE)
    • 当前客户端可以进行写入和读取操作,但是其他客户端不仅不能写入,也不能读取。
  • 元数据锁
    • 当对数据进行增删改查时,加入MDL读锁(共享),修改表的结构时,加入MDL写锁(排他)
  • 意向锁
    • 在执行update类型语句时会自动加上意向锁,而读取语句需要在后面加上LOCK IN SHARE MODE(加上行锁的共享锁,同时加上意向共享锁)。
    • 是一种表锁,避免在DML执行过程中加的行锁和表锁的冲突中,需要依次检查每一行是否加了行锁的步骤,提高了性能。
    • 意向共享锁(IS):与表锁共享锁(read)兼容,与表锁排它锁(write)互斥。
    • 意向排他锁(lX):与表锁共享锁(read)及排它锁(write)都互斥。意向锁之间不会互斥。

3. 行级锁

  • 介绍

    • 行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。
    • InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。
  • 行锁

    • 分为共享锁和排他锁,共享锁和共享锁兼容,排他锁和任何锁都不兼容。

    • 锁住单行记录,防止其他事务对改行记录进行update和delete操作。

      SQL语句行锁类型说明
      INSERT ...排他锁自动加锁
      UPDATE ...排他锁自动加锁
      DELETE ...排他锁自动加锁
      SELECT (正常)不加任何锁
      SELECT ... LOCK IN SHARE MODE共享锁需要手动在SELECT之后加LOCK IN SHARE MODE
      SELECT ... FOR UPDATE排他锁需要手动在SELECT之后加FOR UPDATE
    • 另外前面也提到过,innoDB的数据是基于索引组织的,所以当SQL语句匹配数据的媒介字段没有索引,那么便会导致加锁加的是表锁,而不是行锁。

  • 间隙锁

    • 锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。
    • 当update表中不存在的一栏时,那么假设这一栏存在于表中,这一栏所指向的位置,就是间隙锁所锁住的间隙,防止其他事务在这个间隙进行insert。
  • 临键锁

    • 行锁和间隙锁的组合,锁住记录,同时防止其他事务的插入。
    • 索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁
    • 索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock 退化为间隙锁。
    • 索引上的范围查询(唯一索引)--会访问到不满足条件的第一个值为止。