乐观锁和悲观锁区别:实际场景中的选择
在开发软件或配置系统时,经常会遇到多个用户同时操作同一份数据的情况。比如你和同事一起编辑同一个订单信息,或者多人抢购同一件商品。这时候如果不加控制,很容易出现数据错乱。为了解决这个问题,数据库提供了两种常见的并发控制机制:乐观锁和悲观锁。
悲观锁:先占再说
悲观锁的思路很简单——它假设冲突一定会发生,所以在操作数据前,先把它“锁住”,别人就不能动了。就像你去图书馆看书,先把书揣兜里,别人想看?等我看完再说。
在数据库中,通常用 SELECT ... FOR UPDATE 实现。例如:
START TRANSACTION;<br>SELECT * FROM products WHERE id = 100 FOR UPDATE;<br>-- 此时其他事务无法修改该行<br>UPDATE products SET stock = stock - 1 WHERE id = 100;<br>COMMIT;这种方式适合写操作频繁、冲突概率高的场景,比如库存扣减、银行转账。但缺点也很明显:容易造成阻塞,甚至死锁,性能开销大。
乐观锁:相信世界是美好的
乐观锁正好相反,它认为大多数情况下不会发生冲突,所以不提前加锁。而是在更新时检查数据有没有被别人改过。就像你编辑文档时,系统提示“别人已修改,请确认是否覆盖”。
实现方式通常是给数据加一个版本号字段(version)或时间戳。每次更新时对比版本:
UPDATE products SET stock = 49, version = version + 1 <br>WHERE id = 100 AND version = 1;如果返回影响行数为0,说明版本对不上,别人已经改过了,当前操作失败,需要重试。
这种模式适用于读多写少的场景,比如文章点赞、评论计数,冲突少,效率高,不会阻塞别人。
怎么选?看场景
如果你做的系统是电商下单、资金交易这类高并发写操作,建议用悲观锁,宁可慢一点,也要保证数据安全。但如果是内容管理系统、社交平台这类读多写少的应用,乐观锁更轻量,用户体验更好。
举个例子:两个人同时修改一份软件安装配置文件。如果用悲观锁,先打开的人锁住文件,后打开的只能干等;而用乐观锁,两人都能编辑,保存时检测冲突,谁后提交谁处理合并。这其实就跟 Git 提交代码差不多。
实际项目中,很多框架已经封装好了这两种机制。比如 Hibernate 支持 version 字段自动做乐观锁,MyBatis-Plus 也提供了乐观锁插件。装软件时如果看到相关配置项,现在你应该明白它在干什么了。