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 锁)

定义

  • 排他锁允许事务对某一行数据进行修改,同时禁止其他事务对该行数据进行任何操作(读取或修改)
  • 排他锁是更严格的锁类型。

使用场景

  • 用于写操作(如 INSERTUPDATEDELETE),确保数据修改的唯一性和一致性。

特性

  • 如果某事务持有排他锁,其他事务无法申请任何类型的锁(共享锁或排他锁)。
  • 排他锁主要在写操作或关键数据修改时使用。

加锁方式

  • 显式加排他锁:
    SELECT * FROM table_name WHERE id = 1 FOR UPDATE;
    
  • 隐式排他锁:在 INSERTUPDATEDELETE 操作时,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
隐式锁 高隔离级别或部分只读操作 所有写操作(INSERTUPDATE

4. 注意事项

  • 如果未显式加锁,MySQL 会根据事务隔离级别决定是否加锁:
    • Read Committed:默认不加共享锁,读取最新提交的数据。
    • Repeatable Read:可加共享锁以确保读取的版本一致。
    • Serializable:自动加共享锁,禁止并发写操作。
  • 在事务中显式加锁时,务必明确需求,否则可能会影响性能或导致死锁。

5. 总结

  • 共享锁适合只读场景,多个事务可以同时读取数据。
  • 排他锁适合写操作,确保单事务对数据的唯一修改权限。
  • 根据业务需求选择合适的锁类型,避免不必要的锁争用和死锁。

注意:该内容由由AIGC提供。

posted @ 2024-12-25 09:47  长空nice  阅读(10)  评论(0编辑  收藏  举报