mysql行锁、表锁、意向锁、间隙锁

在 MySQL 中,常用的锁包括行锁表锁意向锁间隙锁等。这些锁通过不同的 SQL 语句和语法来触发,它们的用途、应用场景和锁定方式各不相同。

一、行锁(Row Lock)

行锁是 MySQL 中最常用的锁类型之一,主要用于控制并发事务对单行数据的修改,避免数据冲突。行锁是通过 InnoDB 存储引擎实现的。

1. 行锁的加锁 SQL

  • 使用场景:用于精确锁定某一行记录,以确保同一行的数据不被多个事务同时修改。
加锁方式
  1. SELECT ... FOR UPDATE
    • 排他锁(X 锁),用于修改操作的场景。
    • 当对一行数据执行该语句时,会锁定选中的行,并阻止其他事务对该行的更新和删除。
    • 适用于需要对结果集进行修改的场景。
    sqlCopy code-- 对 id=1 的行加排他锁,其他事务无法更新或删除这行数据 SELECT * FROM table_name WHERE id=1 FOR UPDATE;
  2. SELECT ... LOCK IN SHARE MODE
    • 共享锁(S 锁),用于只读场景。
    • 在加共享锁的情况下,其他事务可以读取同一行的数据,但不能进行更新或删除。
    sqlCopy code-- 对 id=1 的行加共享锁,其他事务可以读取但无法修改 SELECT * FROM table_name WHERE id=1 LOCK IN SHARE MODE;
  3. UPDATEDELETE
    • 在执行 UPDATEDELETE 语句时,InnoDB 会自动对目标行加上排他锁
    sqlCopy code-- 更新 id=1 的行并加上排他锁 UPDATE table_name SET column_name = value WHERE id=1; -- 删除 id=1 的行并加上排他锁 DELETE FROM table_name WHERE id=1;

二、表锁(Table Lock)

表锁是一种用于锁定整个表的粗粒度锁,适用于全表操作大批量修改的场景。在 MySQL 中,表锁的使用需要显式地调用。

1. 表锁的加锁 SQL

  • 使用场景:用于需要锁定整个表的操作,通常在大量数据修改或需要对整个表进行独占访问时使用。
加锁方式
  1. LOCK TABLES ... WRITE
    • 加写锁,锁定整个表,只有持有锁的事务可以对表进行读写,其他事务都将被阻塞。
    sqlCopy code-- 锁定 table_name 表用于写操作 LOCK TABLES table_name WRITE;
  2. LOCK TABLES ... READ
    • 加读锁,允许多个事务同时读取表,但不允许进行更新和删除。
    sqlCopy code-- 锁定 table_name 表用于读操作 LOCK TABLES table_name READ;
  3. UNLOCK TABLES
    • 用于释放表锁。
    sqlCopy code-- 释放所有表锁 UNLOCK TABLES;

三、意向锁(Intention Lock)

意向锁是一种表级别的锁,用于描述事务在表中的锁定意图。意向锁不影响具体行的操作,而是用于优化行锁和表锁之间的协作。意向锁由 InnoDB 自动管理,用户无法手动加锁。

1. 意向锁的类型

  • 意向共享锁(IS 锁):表示事务打算在表中加共享锁
  • 意向排他锁(IX 锁):表示事务打算在表中加排他锁

2. 触发意向锁的 SQL

  • 触发场景:意向锁是在执行行级别加锁操作时,由 InnoDB 自动加锁,用于与表锁进行协作。
    • 当事务在执行 SELECT ... LOCK IN SHARE MODE 时,会加上 IS 锁。
    • 当事务在执行 SELECT ... FOR UPDATEUPDATEDELETE 操作时,会加上 IX 锁。
sqlCopy code-- 这些操作将自动触发意向锁的加锁
SELECT * FROM table_name WHERE id=1 LOCK IN SHARE MODE; -- IS 锁
SELECT * FROM table_name WHERE id=1 FOR UPDATE;         -- IX 锁
UPDATE table_name SET column_name = value WHERE id=1;   -- IX 锁

四、间隙锁(Gap Lock)

间隙锁是一种特殊的行锁,用于防止“幻读”。间隙锁主要用于在“可重复读”隔离级别下,实现一致性和避免并发插入的冲突。

1. 间隙锁的加锁 SQL

  • 使用场景:用于在范围查询时锁定范围内的间隙,防止其他事务在同一范围内插入新行。
加锁方式
  1. 范围查询的 UPDATE 和 DELETE 语句
    • 执行范围查询的 UPDATEDELETE 语句时,InnoDB 会对查询范围内的间隙加上间隙锁,防止插入新行。
    sqlCopy code-- 锁定 id 在 1 到 10 之间的所有行及间隙,防止新插入 UPDATE table_name SET column_name = value WHERE id BETWEEN 1 AND 10; -- 删除 id 在 1 到 10 之间的所有行,并锁定间隙 DELETE FROM table_name WHERE id BETWEEN 1 AND 10;
  2. 范围查询的 SELECT … FOR UPDATE 语句
    • 在执行范围查询的 SELECT ... FOR UPDATE 语句时,也会对范围内的间隙加锁。
    sqlCopy code-- 锁定 id 在 1 到 10 之间的所有行及间隙 SELECT * FROM table_name WHERE id BETWEEN 1 AND 10 FOR UPDATE;

2. 间隙锁的作用

  • 避免幻读:间隙锁的主要目的是防止在范围内插入新行,确保在事务执行过程中范围内的数据不发生变化,防止幻读。
  • 并发性能降低:由于间隙锁会锁定范围内的间隙,可能会影响并发性能,因此一般只在“可重复读”或更高的隔离级别下生效。

五、总结

锁类型SQL 语句场景
行锁SELECT ... FOR UPDATE更新或修改特定行,阻止其他事务并发修改
行锁SELECT ... LOCK IN SHARE MODE读取特定行,只读共享,不允许修改
行锁UPDATEDELETE修改或删除特定行,自动加排他锁
表锁LOCK TABLES ... WRITE/READ锁定整个表,适用于全表操作
意向锁自动触发事务在执行行锁操作时,自动触发表级意向锁
间隙锁范围查询 + FOR UPDATE锁定范围及间隙,防止插入新行
间隙锁范围查询 + UPDATE/DELETE锁定范围及间隙,防止插入新行

在使用锁时,需要根据业务需求和数据库性能做出合理选择,以确保数据一致性和系统的并发性能。

0 0 投票数
Article Rating
订阅评论
提醒
guest
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x