1. 全局锁

全局锁是一种对整个数据库进行锁定的操作,通常用于确保在备份期间数据的一致性。全局锁在操作期间会阻止所有写操作,因此会导致系统处于只读状态。

特点与使用

  • 常用于备份操作:在备份期间,通过加全局读锁防止数据的写入,确保备份期间数据的一致性。
  • 限制
    1. 在主库上加全局锁时,数据库不能进行写操作,备份期间会导致业务停滞。
    2. 在从库上加全局锁时,会影响从主库同步二进制日志(binlog),可能导致主从延迟。

命令示例

  1. 使用 FLUSH TABLES WITH READ LOCK; 来加全局读锁,将数据库置于只读状态。
  2. 使用 UNLOCK TABLES; 来解除全局锁,恢复数据库正常读写。

备份命令示例

在备份时可以使用 mysqldump 命令,加上 --single-transaction 参数来实现一致性备份:

mysqldump --single-transaction -uroot 数据库名 > 备份文件.sql

使用 --single-transaction 参数可以在InnoDB存储引擎中不加全局锁进行一致性备份。


2. 表级锁

表级锁是对单张表加锁的机制,每次锁定整张表,锁定粒度较大,冲突概率高,但实现简单,开销较小。适用于MyISAM、InnoDB、BDB等存储引擎。

表级锁的类型

  1. 表锁(Table Lock)

    • 共享读锁(Read Lock):多个事务可以同时获取共享读锁,允许并发读取数据,但禁止写入操作。
    • 独占写锁(Write Lock):获取写锁的事务独占表的操作权限,禁止其他事务读取或写入,保证修改数据的一致性。

    语法示例

    LOCK TABLES 表名 READ; -- 共享读锁
    LOCK TABLES 表名 WRITE; -- 独占写锁
    UNLOCK TABLES; -- 解除锁
  2. 元数据锁(Meta Data Lock, MDL)

    • 自动加锁机制:MySQL 5.5后引入,无需显式使用,主要用于保护表的元数据一致性。
    • 功能:防止并发的DML和DDL冲突。当一个事务对表结构进行修改(如ALTER TABLE),会阻止其他事务对表执行数据修改操作,直到DDL操作完成。
    • 锁类型:包括 SHARED_READSHARED_WRITEEXCLUSIVE 等类型,分别用于读取、写入、结构变更等不同的操作。

    查询元数据锁状态

    SELECT object_type, object_schema, object_name, lock_type, lock_duration 
    FROM performance_schema.metadata_locks;
  3. 意向锁(Intention Lock)

    • 意向锁用于表明事务对表的操作意图,减少表锁和行锁的冲突,提高并发效率。
    • 类型
      • 意向共享锁(IS):用于声明事务将获取表中某些记录的共享锁,一般用于 SELECT ... LOCK IN SHARE MODE
      • 意向排他锁(IX):用于声明事务将获取表中某些记录的排他锁,一般用于 INSERTUPDATEDELETE 等写操作。
    • 特性:意向锁之间不会互斥,可以共存,允许多个事务在同一张表上进行不同的操作。

    查询意向锁状态

    SELECT object_schema, object_name, index_name, lock_type, lock_mode, lock_data 
    FROM performance_schema.data_locks;

3. 行级锁

行级锁是锁机制中粒度最小的一种锁,仅锁定特定的行数据,锁冲突概率低,并发度高,主要用于InnoDB存储引擎。

行级锁的类型

  1. 共享锁(S锁):用于读取操作。允许多个事务同时对某行数据加共享锁,防止其他事务对该行数据加排他锁。
  2. 排他锁(X锁):用于写操作。获取排他锁的事务可以更新该行数据,阻止其他事务对该行数据加共享锁和排他锁,保证写操作的独占性。

行级锁的SQL操作

  • INSERTUPDATEDELETE:自动加排他锁,确保在写操作期间其他事务不能操作相同的数据行。
  • SELECT ... LOCK IN SHARE MODE:手动加共享锁,确保其他事务不能加排他锁,防止数据被修改。
  • SELECT ... FOR UPDATE:手动加排他锁,确保在读取后进行更新时其他事务无法操作相同的数据行。

4. 间隙锁和Next-Key锁

InnoDB使用Next-Key锁(行锁+间隙锁)来防止幻读问题,在REPEATABLE READ隔离级别下自动生效。

Next-Key锁和间隙锁的机制

  1. 唯一索引等值查询:当查询的是一个唯一索引项且存在匹配记录,Next-Key锁优化为行锁,只锁定该记录。
  2. 普通索引等值查询:查询匹配的记录范围,锁定最后一个满足条件的记录及其前后的间隙。
  3. 范围查询:对满足条件的记录加锁,并锁定范围内的间隙。

间隙锁的作用

间隙锁(Gap Lock)用于防止其他事务在锁定范围内插入数据,以避免幻读。间隙锁之间不互斥,可以共存,但对插入操作有限制。

注意:间隙锁的目的是防止新数据插入,不影响已存在数据的读取和更新操作。


5. 锁机制的总结和对比

锁类型 作用范围 常用场景 优缺点
全局锁 整个数据库 备份操作 粒度最大,阻塞性强,会影响业务
表级锁 整张表 并发低的操作场景 实现简单,开销小,但冲突概率高
元数据锁 表元数据 DDL和DML操作保护 自动加锁,防止结构变更时数据读写冲突
意向锁 表或行 表示操作意图 与行级锁配合使用,提高并发性
行级锁 单行数据 高并发场景 粒度最小,并发性高,适用于InnoDB
Next-Key锁 行和间隙 防止幻读 防止幻读的同时保持行锁的精细控制,适用于可重复读隔离级别
间隙锁 索引间隙 避免新数据插入 防止幻读,允许多个事务加同一间隙锁,但影响插入操作

6. 使用锁的优化

  1. 使用索引优化查询:行级锁依赖索引进行加锁,使用索引可以减少锁的范围,避免表锁或行锁的升级。
  2. 合理选择隔离级别REPEATABLE READ 隔离级别适合大多数场景,避免幻读问题。但在高并发场景中,可以根据业务需求适当放宽隔离级别。
  3. 避免大事务操作:长时间持有锁会影响并发性能,应尽量减少事务的执行时间,将长事务拆分为小事务。
  4. 使用意向锁进行声明:通过意向锁声明操作意图,减少锁冲突,提升事务的并发处理能力。
  5. 监控锁状态:使用 performance_schema 中的相关查询来监控数据库的锁状态,及时识别和解决锁冲突。

锁状态查询示例

  • 查询元数据锁

    SELECT object_type, object_schema, object_name, lock_type, lock_duration 
    FROM performance_schema.metadata_locks;
  • 查询意向锁和行锁

    SELECT object_schema, object_name, index_name, lock_type, lock_mode, lock_data 
    FROM performance_schema.data_locks;

通过对锁机制的合理使用,可以在高并发的数据库环境中提高数据一致性、避免冲突和数据竞争问题,从而实现高效、稳定的数据库性能。