【MySQL悲观锁怎么实现】面试题精解
📚 2025年Java面试宝典:
🔗 https://pan.baidu.com/s/1RUVf75gmDVsg8MQp4yRChg?pwd=9b3g
提取码:9b3g(建议保存备用!)
🔍 什么是MySQL悲观锁?
简单来说,悲观锁是一种“先加锁再操作”的并发控制策略。它的核心思想是:假设其他事务一定会修改数据,所以操作前先锁定资源。在MySQL中,悲观锁常用于高并发写场景,比如库存扣减、订单支付等,避免数据冲突。
🔧 MySQL悲观锁的两种实现方式
1️⃣ 共享锁(Shared Lock)
- 语法:
SELECT ... LOCK IN SHARE MODE - 作用:允许其他事务读,但禁止写。
- 适用场景:读多写少,且需要确保读取的数据不被修改。
-- 示例:查询商品库存并加共享锁
SELECT stock FROM products WHERE id = 100 LOCK IN SHARE MODE;

2️⃣ 排他锁(Exclusive Lock)
- 语法:
SELECT ... FOR UPDATE - 作用:禁止其他事务读和写(包括共享锁)。
- 适用场景:高并发写操作(如秒杀)。
-- 示例:扣减库存前加排他锁
BEGIN;
SELECT stock FROM products WHERE id = 100 FOR UPDATE; -- 锁定数据
UPDATE products SET stock = stock - 1 WHERE id = 100; -- 执行修改
COMMIT;

⚠️ 使用悲观锁的注意事项
-
必须在事务中生效
单独执行SELECT ... FOR UPDATE不会持久加锁,需配合BEGIN/COMMIT。 -
索引是高效锁的前提
WHERE条件字段必须有索引,否则会锁表(行锁→表锁),性能急剧下降! -
死锁风险
多个事务互相等待锁释放会导致死锁。解决方案:- 统一SQL执行顺序(如先锁A表再锁B表)
- 设置事务超时时间:
innodb_lock_wait_timeout=50(默认50秒)
💡 面试高频问题
Q:什么时候用悲观锁?什么时候用乐观锁?
- 悲观锁:写冲突概率高(如金融交易)
- 乐观锁:写冲突概率低(如评论点赞),通过版本号(
version字段)或时间戳实现。
Q:FOR UPDATE 锁的是行还是索引?
锁的是索引!如果WHERE条件无索引,直接锁全表;如果是二级索引,会同时锁二级索引+主键索引。
🚀 如何优化悲观锁性能?
- 缩小锁定范围
用精确条件(如WHERE id=100)而非范围查询(WHERE status=1)。 - 缩短事务时长
锁定时长 = 事务执行时间,复杂逻辑拆分成多个短事务。 - 避免长事务
监控慢查询日志,及时优化耗时操作。
🎁 面试福利:
如果你需要面试鸭会员,通过 面试鸭返利网 购买可返利25元!海量大厂真题+答案持续更新中👇
👉 更多MySQL锁机制深度解析:面试鸭返利网



