MySQL 的乐观锁和悲观锁是什么?

MySQL 的乐观锁和悲观锁是什么?

在并发环境下,为了避免数据竞争和保证数据一致性,可以使用不同的锁策略。乐观锁和悲观锁是两种常见的并发控制机制,它们在锁定数据时的理念和实现方式上有显著区别。


1. 悲观锁(Pessimistic Lock)

定义

  • 悲观锁是一种保守的并发控制策略,假设数据在被访问时会发生并发修改,因此在操作数据之前会将其锁定,确保其他事务无法修改数据。
  • 使用悲观锁的事务在操作数据时会 主动加锁,以防止其他事务对数据的读写操作。

实现方式

  • 在 MySQL 中,悲观锁通常依赖于数据库的锁机制,例如 行锁表锁
  • 常用语法
    • 使用 SELECT ... FOR UPDATELOCK TABLES 来实现悲观锁。

示例

事务 A 和事务 B 需要修改同一条记录:

  1. 事务 A 执行以下语句:
START TRANSACTION; SELECT * FROM orders WHERE id = 1 FOR UPDATE;

此时,事务 A 加锁,事务 B 无法操作 id = 1 的记录。

  1. 事务 B 尝试修改相同记录时会被阻塞,直到事务 A 提交或回滚。

适用场景

  • 数据冲突较频繁的场景,例如高并发情况下对相同资源的修改操作。
  • 在修改之前需要保证数据的强一致性。

2. 乐观锁(Optimistic Lock)

定义

  • 乐观锁是一种开放的并发控制策略,假设数据在被操作期间不会发生冲突,因此不在操作前加锁,而是在提交数据时通过 冲突检测机制 检测是否存在数据竞争。
  • 如果检测到数据已被其他事务修改,则回滚并重新尝试。

实现方式

  • 乐观锁通常通过 版本号时间戳 来实现。
  • 常用逻辑
  1. 查询数据时,读取记录的版本号或时间戳。
  2. 修改数据时,检查记录的版本号或时间戳是否与查询时一致。
  3. 如果一致,则更新记录并增加版本号;否则,说明数据被其他事务修改,需要重试或终止操作。

示例

表结构如下:

CREATE TABLE orders ( id INT PRIMARY KEY, stock INT, version INT );

事务更新逻辑:

  1. 查询数据:
SELECT stock, version FROM orders WHERE id = 1;
  1. 更新数据:
UPDATE orders SET stock = stock - 1, version = version + 1 WHERE id = 1 AND version = 当前版本号;
  1. 检查受影响的行数:
  • 如果行数为 0,表示版本号已变化,需要重试或终止操作。

适用场景

  • 数据冲突较少的场景,例如读多写少的业务场景。
  • 高并发情况下,提高性能,同时保证一定程度的数据一致性。

3. 乐观锁与悲观锁的对比

对比项 乐观锁 悲观锁
理念 假设冲突很少,操作时不加锁,依赖冲突检测。 假设冲突频繁,操作时加锁,防止冲突发生。
实现方式 依赖版本号、时间戳或 CAS(Compare and Swap)。 使用数据库的锁机制,例如 FOR UPDATE
性能 无锁操作,性能较高,适合高并发场景。 需要加锁,性能较低,适合冲突频繁场景。
冲突检测 提交时检测是否冲突。 通过加锁避免冲突。
适用场景 读多写少,冲突较少的场景。 写多且冲突频繁的场景。

总结

  • 悲观锁 通过锁机制保证操作安全,适合冲突频繁的场景,但性能较低。
  • 乐观锁 依赖版本控制机制来检测冲突,适合冲突较少的高并发场景,性能更优。
  • 在实际开发中,可以根据具体业务需求选择合适的锁机制。例如:
  • 数据一致性要求极高时使用 悲观锁
  • 数据冲突概率较低时使用 乐观锁
posted @   Eiffelzero  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
历史上的今天:
2022-12-15 1945. 字符串转化后的各位数字之和
点击右上角即可分享
微信分享提示