news 2026/5/1 7:09:21

如何避免MySQL死锁?资深DBA的9条黄金法则

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何避免MySQL死锁?资深DBA的9条黄金法则

死锁是数据库里很常见的问题:两个或多个事务互相等待对方释放锁,结果谁也动不了。

MySQL的InnoDB引擎会自己自动检测死锁,并且回滚其中一个事务来解决,但这种情况如果经常遇到的话,会很影响性能和用户体验。

其实,只要注意一些设计细节,就能大大减少甚至避免死锁。

下面是几个最实用的方法:


1. 事务要短,动作要快

事务越长,锁住数据的时间就越久,别人就越容易“撞上”你。

正确做法:只在事务里做必要的数据库操作,别把业务逻辑(比如调接口、算数据)塞进去。

sql

-- 不推荐:事务中混杂业务逻辑 START TRANSACTION; SELECT * FROM users WHERE id = 1; -- 假设此处有耗时的业务处理... UPDATE accounts SET balance = balance - 100 WHERE user_id = 1; UPDATE orders SET status = 'paid' WHERE user_id = 1; COMMIT; -- 推荐:事务只包含必要数据库操作 START TRANSACTION; UPDATE accounts SET balance = balance - 100 WHERE user_id = 1; UPDATE orders SET status = 'paid' WHERE user_id = 1; COMMIT;


2. 所有事务按同一个顺序操作表

这是避免死锁最有效的一招!

比如:如果多个事务都要改 users 和 orders 表,那就统一先改 users,再改 orders。不要有的先改 users,有的先改 orders。

sql

-- 所有地方都这样写: UPDATE users SET ... WHERE id = 1; UPDATE orders SET ... WHERE user_id = 1;

只要顺序一致,就不会出现“A等B、B等A”的循环等待。


3. 给表加合适的索引

InnoDB 的行锁是靠索引来实现的。如果查询没用到索引,MySQL 就可能锁住整张表(或很多无关的行),大大增加死锁风险。

建议

  • 经常用来查或更新的字段(比如 user_id)要建索引。
  • 用 EXPLAIN 看看 SQL 是否命中索引。
sql

CREATE INDEX idx_user_id ON orders(user_id);


4. 别用太高的隔离级别(除非必要)

MySQL 默认是 REPEATABLE READ,它会加“间隙锁”,防止幻读,但也更容易死锁。

如果你的业务能接受“读已提交”(比如允许看到别人刚提交的数据),可以改成:

sql

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

这样锁的范围更小,死锁概率更低。


5. 显式加锁时要小心

如果你要用 SELECT ... FOR UPDATE 锁行,一定要确保:

  • 条件能命中索引;
  • 锁的行尽量少;
  • 事务尽快结束。
sql

-- 安全:通过主键或索引锁定一行 SELECT * FROM accounts WHERE user_id = 1 FOR UPDATE;

如果 user_id 没索引,这条语句可能锁住成千上万行!


6. 应用层要有重试机制

死锁偶尔还是会发生。这时候,应用应该:

  • 捕获死锁错误(MySQL 错误码 1213 或 SQLSTATE '40001');
  • 自动重试几次(比如最多 2~3 次);
  • 每次重试前等一小会儿(比如 100ms、200ms…)。
java

// 伪代码示例 for (int i = 0; i < 3; i++) { try { doDatabaseUpdate(); break; // 成功就退出 } catch (DeadlockException e) { sleep(100 * (i + 1)); // 等一下再试 } }


7. 大批量更新要分批做

一次更新几万行?这很容易锁住大量数据,引发死锁或卡顿。

正确做法:每次只改 500~1000 行,改完提交,再继续。

sql

-- 分批更新 UPDATE large_table SET status = 'done' WHERE create_time < '2023-01-01' AND status != 'done' LIMIT 1000; -- 循环执行,直到没有数据可更新


8. 避免热点数据被频繁修改

比如一个全局计数器,所有请求都去 UPDATE counter SET value = value + 1,那这一行就成了堵点。

解决办法:用分桶计数。

sql

-- 把计数分散到 10 个桶里 UPDATE counter_buckets SET value = value + 1 WHERE name = 'views' AND bucket = FLOOR(RAND() * 10); -- 查总数时再加起来 SELECT SUM(value) FROM counter_buckets WHERE name = 'views';


9. 出问题了怎么查?

看最近一次死锁详情:

sql

SHOW ENGINE INNODB STATUS;

找LATEST DETECTED DEADLOCK部分。

查当前正在运行的事务(MySQL 8.0+):

sql

SELECT * FROM performance_schema.data_locks; SELECT * FROM information_schema.INNODB_TRX;


总结

1.事务要短:别拖着不提交。 2.顺序要一致:所有人按相同顺序改表。 3.索引要到位:避免锁太多无关数据。 4.出错要重试:应用层兜底处理死锁。 5.大批量要分批:别一次锁太多行。

死锁没法完全杜绝,但只要做好这些,基本就不会再被它困扰了!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 15:13:25

项目风险管理:LobeChat识别潜在威胁

项目风险管理&#xff1a;LobeChat识别潜在威胁 在AI技术加速落地的今天&#xff0c;企业部署大语言模型&#xff08;LLM&#xff09;应用的热情高涨。然而&#xff0c;理想与现实之间往往存在巨大落差——许多团队在初期兴奋地接入GPT API后不久便发现&#xff1a;界面体验割裂…

作者头像 李华
网站建设 2026/5/1 7:04:14

AutoCAD字体管理终极指南:告别字体缺失困扰的智能解决方案

AutoCAD字体管理终极指南&#xff1a;告别字体缺失困扰的智能解决方案 【免费下载链接】FontCenter AutoCAD自动管理字体插件 项目地址: https://gitcode.com/gh_mirrors/fo/FontCenter 还在为AutoCAD图纸打开时的字体缺失提示而烦恼吗&#xff1f;FontCenter作为一款革…

作者头像 李华
网站建设 2026/4/17 22:41:40

2026秋招大模型就业热点:大厂提前招聘,AI岗位激增10倍!抢占未来先机,这些岗位不容错过!

2026 届全国普通高校毕业生规模预计突破 1200 万人大关&#xff0c;就业市场的 “内卷” 态势依旧激烈。但今年秋招却迎来了不一样的新局面 —— 各大企业抢人提前半个月&#xff0c;AI 岗位需求暴涨 10 倍&#xff0c;央企也加入 “扩招大军”。对于应届生来说&#xff0c;这既…

作者头像 李华
网站建设 2026/4/25 13:20:25

汇编语言全接触-31.列表视图控件

本课中我们将学习如何创建和使用列表视图控件。 理论&#xff1a;列表视图控件和树型视图、丰富文本编辑控件一样是通用控件的一种。可能您都已经知道了列表视图控件&#xff0c;只不过是不知道它的确切名字而已。列表视图控件可以用来很好地显示项目。在这方面它和列表框相同&…

作者头像 李华
网站建设 2026/4/22 20:20:57

Obsidian Style Settings插件:解锁个性化笔记体验的终极指南

Obsidian Style Settings插件&#xff1a;解锁个性化笔记体验的终极指南 【免费下载链接】obsidian-style-settings A dynamic user interface for adjusting theme, plugin, and snippet CSS variables within Obsidian 项目地址: https://gitcode.com/gh_mirrors/ob/obsidi…

作者头像 李华
网站建设 2026/4/22 21:04:58

TegraRcmGUI:Windows平台Nintendo Switch自定义payload注入完整指南

TegraRcmGUI&#xff1a;Windows平台Nintendo Switch自定义payload注入完整指南 【免费下载链接】TegraRcmGUI C GUI for TegraRcmSmash (Fuse Gele exploit for Nintendo Switch) 项目地址: https://gitcode.com/gh_mirrors/te/TegraRcmGUI TegraRcmGUI是一款专为Windo…

作者头像 李华