MySQL中的锁

MySQL中的锁

MySQL中有哪些锁?这些锁的作用又是什么?

MySQL中的锁按照颗粒度从粗到细分为:

  • 全局锁
  • 表级锁
  • 行级锁

SQL分类:

  1. DDL(Data Definition Language)数据定义语言:用来操作数据库、表、列等。常用语句:CREATE、ALTER、DROP。

  2. DML(Data Manipulation Language)数据操作语言:用来操作数据库中表里的数据。常用语句:INSERT、 UPDATE、DELETE。

  3. DCL(Data Control Language)数据控制语言:用来操作访问权限和安全级别。常用语句:GRANT、DENY。

  4. DQL(Data Query Language)数据查询语言:用来查询数据。常用语句:SELECT。

全局锁(Global Lock)

全局锁会锁住整个数据库并且数据库处于只读状态,只能进行DQL操作不能进行DDL(包括定义、改变表结构、数据类型、表之间链接的操作)和DML操作,适用于需要保证数据一致性的场景比如数据备份。

数据备份加锁步骤:

  1. 加全局锁,之后只能进行DQL操作。
    SQL
    1
    FLUSH TABLES WITH READ LOCK;
  2. 使用mysqldump备份数据库。
    bash
    1
    mysqldump --user user --password database_name --result-file=path/to/file.sql
  3. 备份完成后解开全局锁。
    SQL
    1
    UNLOCK TABLES;
  4. 正常进行DDL、DML、DQL操作。

表级锁

表级锁分为:

  • 表锁
  • 元数据锁
  • 意向锁

表锁(Table Lock)

SQL
1
2
3
4
5
-- 给表加锁
LOCK TABLES table_name [READ | WRITE]

-- 释放锁
UNLOCK TABLES;

表锁锁的是整张表,表所细分为读锁和写锁。

  • 读锁(Read Lock)

多个事务可以同时读表,但是无法写。

  • 写锁(Write Lock)

一个事务在获取到写锁后其他事务无法读写这张表,等到写锁被释放其他事务才可以继续读写。

元数据锁(Meta Data Lock)

元数据锁锁定的是表结构(包括表定义、索引定义),当执行改变表结构的操作(ALTER TABLE、DROP TABLE)时MySQL会自动给表加上元数据锁以防止并发的DDL操作(比如CREATE、ALTER、DROP)和DML(比如INSERT、UPDATE、DELETE)操作发生冲突。

意向锁(Intention Lock)

意向锁是MySQL自动加的。

意向锁不会阻塞其他事务的表锁操作,只是用来表明某个事务打算对某些行加锁。

意向共享锁(Intention Shared Lock):当一个事务想要在某些行上加共享锁时,首先需要在表级别加意向共享锁。

意向排他锁(Intention Exclusive Lock):当一个事务想要在某些行上加排他锁时,首先需要在表级别加意向排他锁。

行级锁

行级锁是粒度最小的锁,是针对于索引字段加的锁,只对于当前操作的一行或者多行进行加锁。

行级锁操作粒度最小,并发度高。但是加锁开销最大,可能出现死锁。

行级锁分为:

  • 行锁
  • 间隙锁
  • 临键锁

行锁(Row Lock)

行锁锁定表中的一行或者多行。

因为行锁只锁定特定的行,所以不影响整张表,是innoDB主要的锁类型。

行锁分为:

  • 共享锁

如果给行加上共享锁,那么其他事务将不可获得排他锁,其他事务只能获取共享锁并且只能读这些行。

  • 排他锁

只允许获取到排他锁的事务读写,其他事务将不能获取到共享锁和排他锁直到排他锁被释放。

间隙锁(Gap Lock)

当用范围条件而不是相等条件索引数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁。对于键值在条件范围内但并不存在的记录,叫做间隙。间隙锁帮我们解决幻读问题。

临键锁(Next-Key Lock)

临键锁是行锁与间隙锁的组合,它的锁定范围既包含行又包含索引区间。

自增锁(AUTO-INC Lock)

如果一个表中含有自增字段,MySQL会使用自增锁来确保并发插入操作时自增字段的唯一性和有序性。

自增锁在事务提交时释放。

外键锁(Foreign Key Lock)

使用外键约束时,innoDB会对相关行加锁确保父表中的行在存在关联的子表行时不会被删除或者更新。

评论