上一篇
想象一下双十一零点,数万用户同时点击"立即购买"按钮的场景,小明的购物车里有一款限量100件的羽绒服,当他点击提交订单时,系统显示"库存不足",但奇怪的是,刷新页面后发现库存显示还有5件——这就是典型的并发控制问题,MySQL如何通过锁机制避免这种混乱?让我们一探究竟。
MySQL的锁机制就像是图书馆的借阅系统,当一本书被借走时,系统会标记为"已借出",其他人只能等待或选择其他书籍,MySQL通过类似的方式确保数据的一致性。
锁的核心作用:
共享锁(S锁):
SELECT * FROM products WHERE id=1 LOCK IN SHARE MODE;
排他锁(X锁):
SELECT * FROM products WHERE id=1 FOR UPDATE;
表级锁:
行级锁:
页级锁:
InnoDB的行锁通过索引实现,没有走索引的查询会退化为表锁。
三种行锁算法:
记录锁(Record Lock):锁定索引中的单条记录
-- 锁定id=1的记录 SELECT * FROM users WHERE id=1 FOR UPDATE;
间隙锁(Gap Lock):锁定索引记录间的间隙
-- 锁定id在5到10之间的间隙,防止插入 SELECT * FROM users WHERE id BETWEEN 5 AND 10 FOR UPDATE;
临键锁(Next-Key Lock):记录锁+间隙锁的组合
错误做法:
-- 线程1 SELECT stock FROM products WHERE id=1; -- 查到stock=100 -- 线程2也执行相同查询 UPDATE products SET stock=99 WHERE id=1; -- 可能覆盖线程2的修改
正确做法:
BEGIN; -- 加排他锁 SELECT stock FROM products WHERE id=1 FOR UPDATE; -- 检查库存 UPDATE products SET stock=stock-1 WHERE id=1; COMMIT;
死锁检测:
SHOW ENGINE INNODB STATUS;
查看LATEST DETECTED DEADLOCK部分
锁等待超时:
-- 设置锁等待超时时间(秒) SET innodb_lock_wait_timeout=50;
查看当前锁信息:
SELECT * FROM performance_schema.data_locks;
尽量使用索引:没有索引会导致行锁升级为表锁
控制事务大小:大事务会增加锁持有时间
合理设置隔离级别:
-- 通常使用READ COMMITTED或REPEATABLE READ SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
避免热点数据竞争:
死锁预防:
-- 0: 传统模式(每个插入语句完成后释放) -- 1: 连续模式(默认,事务完成后释放) -- 2: 交叉模式(最高并发,但可能不连续) SET innodb_autoinc_lock_mode=1;
NOWAIT和SKIP LOCKED语法:
-- 如果无法立即获取锁则返回错误 SELECT * FROM table FOR UPDATE NOWAIT; -- 跳过被锁定的行 SELECT * FROM table FOR UPDATE SKIP LOCKED;
性能优化:
增强的监控能力:
MySQL的锁机制就像交通信号灯,需要在通行效率(并发性能)和安全规则(数据一致性)之间找到平衡点,理解不同锁的特性,结合实际业务场景合理应用,才能构建出既高效又可靠的数据库系统,下次当你遇到并发问题时,不妨先问问:这里需要什么样的"交通管制"?
本文由 斋光远 于2025-07-31发表在【云服务器提供商】,文中图片由(斋光远)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/498144.html
发表评论