MySQL锁

一、MySQL 锁的分类

1. 按锁的粒度

说明 适用引擎
表锁 锁定整个表,并发性低,但开销小。 MyISAM、InnoDB(部分场景)
行锁 仅锁定需要操作的行,并发性高,但开销较大。 InnoDB
页锁 锁定数据页(介于表锁和行锁之间),较少使用。 BDB(已废弃)

2. 按锁的模式

说明
共享锁(S锁) 允许其他事务读取被锁定的行,但禁止修改(读锁)。
排他锁(X锁) 禁止其他事务读取或修改被锁定的行(写锁)。

二、锁的应用场景

1. 隐式锁(自动加锁)

MySQL 在大多数情况下会自动处理锁,无需手动加锁。例如:

  • DML 语句(INSERT/UPDATE/DELETE):InnoDB 默认对受影响的行加排他锁(X锁)。

  • SELECT 查询:默认不加锁,但根据隔离级别可能通过 MVCC(多版本并发控制)读取快照数据。

示例:

-- InnoDB 会为被更新的行自动加排他锁
UPDATE products SET stock = stock - 1 WHERE id = 100;

2. 显式锁(手动加锁)

在某些高并发或需要强制保证一致性的场景中,需手动加锁。

示例:

START TRANSACTION;
SELECT * FROM orders WHERE id = 100 FOR UPDATE; -- 显式锁定行
UPDATE orders SET amount = 200 WHERE id = 100;
COMMIT;

3. 对比

显式锁 隐式锁
控制权 用户主动声明 引擎自动管理
可见性 可直接监控 冲突时转为显式锁才可见
锁粒度 支持表级、行级、间隙锁 主要为行级锁
典型语句 LOCK TABLESFOR UPDATE INSERT, 普通UPDATE
事务要求 需显式事务支持 隐式/显式事务均可

三、锁的兼容性

1. 锁模式兼容性(共享锁 vs 排他锁)

   共享锁(S) 排他锁(X)
共享锁(S) 兼容     冲突
排他锁(X) 冲突     冲突

说明

  • 共享锁之间兼容:多个事务可同时持有共享锁(如并发读取)。

  • 共享锁与排他锁冲突:持有共享锁时,禁止其他事务加排他锁(保证数据不被修改)。

  • 排他锁之间互斥:确保同一资源只能被一个事务独占修改。

2. 锁粒度兼容性(行级锁 vs 表级锁)

当前持有锁 \ 请求锁 表级S锁 表级X锁 行级S锁 行级X锁
表级S锁         兼容   冲突   冲突   冲突
表级X锁         冲突   冲突   冲突   冲突
行级S锁         冲突   冲突   兼容*   冲突*
行级X锁         冲突   冲突   冲突*   冲突*

  1. 行级锁兼容性

    • 不同行的行级锁(无论S/X)均兼容(如事务A锁定id=1,事务B可锁定id=2)。

    • 同一行的行级锁需按锁模式判断兼容性。

  2. 表级锁互斥性

    • 表级锁会阻塞所有其他粒度的锁请求(如持有表级锁时,其他事务无法加行级锁)。

3. 总结

  1. 锁模式冲突:S锁允许并发读,X锁要求独占。

  2. 锁粒度冲突:表级锁与行级锁互斥。

四、锁的使用注意事项

1. 锁的粒度选择

优先使用行锁:通过索引精准锁定目标行,避免锁升级为表锁。

-- 若 id 是索引列,仅锁定 id=100 的行
SELECT * FROM users WHERE id = 100 FOR UPDATE;

-- 若无索引,InnoDB 会锁全表
SELECT * FROM users WHERE name = '***' FOR UPDATE;

2. 避免死锁

3. 监控锁状态

查看当前锁信息

-- 查看正在等待的锁
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;

-- 查看锁等待关系
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;

-- 查看长事务(可能持有锁)
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;

你可能感兴趣的:(数据库,数据库,mysql)