1. 数据库锁机制的必要性
在多人同时操作数据库的场景下,如果没有合理的并发控制机制,就会出现各种数据异常问题。最常见的就是丢失更新问题:当两个事务同时读取同一行数据,然后基于读取的值进行修改并写回数据库时,后提交的事务会覆盖前一个事务的修改。
假设我们有一个商品库存表,当前库存为100。事务A和事务B同时读取到库存为100,事务A将库存减10变为90并提交,事务B将库存减20变为80并提交。最终库存显示为80,但实际上应该为70(100-10-20)。这就是典型的并发更新导致的数据不一致。
数据库锁机制就是为了解决这类并发问题而设计的。通过合理的加锁策略,可以确保数据在并发访问时的一致性。MySQL主要提供了两种锁策略:乐观锁和悲观锁,它们分别适用于不同的业务场景。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 悲观锁的核心原理与实现
2.1 什么是悲观锁
悲观锁(Pessimistic Lock)是一种"先加锁再访问"的并发控制策略。它假设并发冲突发生的概率很高,因此在数据被访问前就会先加锁,确保在自己操作期间不会有其他事务修改数据。
这种策略就像图书馆的"预约借书"制度:当你想要借阅一本热门书籍时,会先进行预约锁定,确保在你来取书之前别人无法借走,即使你可能最终不会来取书。
2.2 MySQL中的悲观锁实现方式
在MySQL中,悲观锁主要通过SELECT...FOR UPDATE语句实现:
sql复制START TRANSACTION;
-- 对id=1的商品记录加悲观锁
SELECT stock FROM products WHERE id=1 FOR UPDATE;
-- 执行业务逻辑...
UPDATE products SET stock=stock-1 WHERE id=1;
COMMIT;
FOR UPDATE子句会在查询时对匹配的行加上排他锁(X锁),其他事务无法对这些行加锁或修改,直到当前事务提交或回滚。
2.3 悲观锁的适用场景
悲观锁最适合以下场景:
- 冲突频率高的环境:当多个事务频繁修改同一条记录时
- 长事务场景:业务逻辑复杂、执行时间较长的事务
- 关键业务数据:如金融系统的账户余额、库存系统的重要物资等
注意:悲观锁会显著降低系统并发性能,不适合在高并发但冲突少的场景使用。不当使用可能导致大量事务等待,甚至死锁。
2.4 悲观锁的优缺点分析
优点:
- 保证强一致性:确保数据在事务期间不会被其他事务修改
- 实现简单:直接使用数据库提供的锁机制
- 适合复杂业务:长事务中能保持数据一致性
缺点:
- 性能开销大:加锁操作消耗资源,降低系统吞吐量
- 死锁风险:不当使用可能导致死锁情况
- 扩展性差:不适合分布式系统环境
3. 乐观锁的核心原理与实现
3.1 什么是乐观锁
乐观锁(Optimistic Lock)采取与悲观锁相反的思路:它假设并发冲突发生的概率很低,因此不会在读取数据时加锁,而是在更新时检查数据是否被其他事务修改过。
这就像图书馆的"先到先得"制度:任何人都可以直接取书阅读,但归还时如果发现书已经被更新(比如有人做了批注),就需要处理这个冲突。
3.2 MySQL中乐观锁的实现方式
乐观锁通常通过版本号或时间戳实现。常见做法是在表中增加一个version字段:
sql复制-- 商品表结构
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100),
stock INT,
version INT DEFAULT 0
);
-- 乐观锁更新操作
START TRANSACTION;
-- 1. 读取数据和当前版本号
SELECT stock, version FROM products WHERE id
