MySQL共享锁,排他锁
在 MySQL 中,共享锁(S 锁) 和 排他锁(X 锁) 是两种主要的锁机制,用于处理事务的并发控制。它们的作用和行为如下:
1. 共享锁 (S 锁)
定义:
- 共享锁允许事务对某一行数据进行读取,但禁止其他事务修改该行数据。
- 多个事务可以同时对一行数据加共享锁。
使用场景:
- 通常用于只读操作,确保数据在读取过程中不会被其他事务修改。
特性:
- 如果某事务持有共享锁,其他事务可以继续申请共享锁,但不能申请排他锁。
- 共享锁主要在高并发的读取场景中使用。
加锁方式:
- 显式加共享锁:
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;
- 隐式共享锁:在
SELECT
操作中,如果表的事务隔离级别是 Serializable,会自动加共享锁。
行为示例:
-- 事务 A 加共享锁
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE;
-- 事务 B 尝试修改同一行
START TRANSACTION;
UPDATE table_name SET column1 = 'new_value' WHERE id = 1; -- 阻塞或失败
2. 排他锁 (X 锁)
定义:
- 排他锁允许事务对某一行数据进行修改,同时禁止其他事务对该行数据进行任何操作(读取或修改)。
- 排他锁是更严格的锁类型。
使用场景:
- 用于写操作(如
INSERT
、UPDATE
、DELETE
),确保数据修改的唯一性和一致性。
特性:
- 如果某事务持有排他锁,其他事务无法申请任何类型的锁(共享锁或排他锁)。
- 排他锁主要在写操作或关键数据修改时使用。
加锁方式:
- 显式加排他锁:
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
- 隐式排他锁:在
INSERT
、UPDATE
、DELETE
操作时,MySQL 会自动加排他锁。
行为示例:
-- 事务 A 加排他锁
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
-- 事务 B 尝试读取或修改同一行
START TRANSACTION;
SELECT * FROM table_name WHERE id = 1 LOCK IN SHARE MODE; -- 阻塞或失败
UPDATE table_name SET column1 = 'new_value' WHERE id = 1; -- 阻塞或失败
3. 共享锁与排他锁的对比
特性 | 共享锁 (S 锁) | 排他锁 (X 锁) |
---|---|---|
允许的操作 | 多个事务可以同时读取数据 | 仅允许一个事务对数据进行修改 |
加锁后的影响 | 阻止其他事务修改数据,但允许读取 | 阻止其他事务读取或修改数据 |
使用场景 | 只读场景,确保读取数据的一致性 | 写场景,确保修改数据的一致性 |
显式加锁语法 | LOCK IN SHARE MODE |
FOR UPDATE |
隐式锁 | 高隔离级别或部分只读操作 | 所有写操作(INSERT 、UPDATE ) |
4. 注意事项
- 如果未显式加锁,MySQL 会根据事务隔离级别决定是否加锁:
- Read Committed:默认不加共享锁,读取最新提交的数据。
- Repeatable Read:可加共享锁以确保读取的版本一致。
- Serializable:自动加共享锁,禁止并发写操作。
- 在事务中显式加锁时,务必明确需求,否则可能会影响性能或导致死锁。
5. 总结
- 共享锁适合只读场景,多个事务可以同时读取数据。
- 排他锁适合写操作,确保单事务对数据的唯一修改权限。
- 根据业务需求选择合适的锁类型,避免不必要的锁争用和死锁。
注意:该内容由由AIGC提供。