MySQL锁大全
MySQL中的锁机制是保证多个并发事务之间数据一致性的重要手段。在并发场景下,如果不使用合适的锁机制,可能会导致数据不一致或者出现并发问题。本文将介绍MySQL中常见的锁类型及其使用示例。
1. 共享锁和排他锁
MySQL中最基本的两种锁类型是共享锁(Shared Lock)和排他锁(Exclusive Lock)。共享锁可以被多个事务同时持有,用于读取数据;而排他锁只能被一个事务持有,用于修改数据。
1.1 共享锁示例
-- 会话1
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;
-- 读取数据
-- 会话2
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;
-- 读取数据
-- 会话3
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;
-- 读取数据
1.2 排他锁示例
-- 会话1
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
-- 修改数据
-- 会话2
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
-- 因为排他锁被会话1持有,会话2需要等待会话1释放锁才能继续执行
-- 会话3
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
-- 因为排他锁被会话1持有,会话3需要等待会话1释放锁才能继续执行
2. 表锁和行锁
MySQL中的锁可以作用在表级别或者行级别。表锁是一种粗粒度锁,可以锁定整个表,适用于对整个表进行操作的场景;而行锁是一种细粒度锁,只锁定表中的某一行或多行,适用于并发读写操作的场景。
2.1 表锁示例
-- 会话1
LOCK TABLES table_name WRITE;
-- 对表进行写操作
-- 会话2
LOCK TABLES table_name READ;
-- 对表进行读操作
-- 会话3
LOCK TABLES table_name WRITE;
-- 因为表锁被会话1持有,会话3需要等待会话1释放锁才能继续执行
2.2 行锁示例
-- 会话1
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
-- 修改数据
-- 会话2
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
-- 因为行锁被会话1持有,会话2需要等待会话1释放锁才能继续执行
-- 会话3
START TRANSACTION;
SELECT * FROM table_name WHERE id = 2 FOR UPDATE;
-- 不同行的锁是相互独立的,因此会话3能够继续执行
3. 乐观锁和悲观锁
除了基本的共享锁和排他锁外,MySQL还提供了乐观锁和悲观锁机制。乐观锁假设并发冲突很少发生,不主动加锁,而是在提交事务时检查数据是否被修改;悲观锁则认为并发冲突经常发生,主动对数据进行加锁。
3.1 乐观锁示例
-- 会话1
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1;
-- 修改数据
-- 会话2
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1;
-- 修改数据
-- 会话1
COMMIT;
-- 提交事务时,检查数据是否被修改,如果被修改则回滚事务
-- 会话2
COMMIT;
-- 提交事务时,检查数据是否被修改,如果被修改则回滚事务,否则提交修改