无尘阁日记

无尘阁日记

数据库死锁(Deadlock)」错误解决
2025-11-08

image.png

这是个「数据库死锁(Deadlock)」错误

弹窗里写着:SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction
意思是:后台在往数据库(多半是 MySQL/InnoDB)插入 CreateSheetDetails 这条记录时,和另一条并发事务互相等待锁,形成闭环,数据库主动回滚了其中一方,于是前端报错。

会怎么触发

  • 多人/多进程同时操作同一批数据:比如同时“复制模板/创建表单/保存明细”,互相锁住了相关行或索引。

  • 外键/唯一键检查导致的锁冲突SubjectId/TemplateSheetId/CreatedSheetId/ProjectId 等外键在校验父表时,恰好别的事务在更新/删除父表。

  • 长事务/大扫描:没有合适索引导致校验或查重走全表或范围锁,锁住的范围过大。

  • 重复点击/并发重试:前端按钮点了多次,后端同时跑了多条插入。

  • 统一加锁顺序不一致:两个事务访问表、行的顺序不同,最容易产生死锁。

你现在可以怎么处理(非开发同学)

  1. 点“确定”后重试一次(间隔 2–5 秒)。死锁通常是偶发的,重试就能成功。

  2. 避免连续快速点击同一按钮,或同时在多个窗口/多人对同一项目做相同操作。

  3. 若频繁出现:记录发生时间、操作步骤和项目编号,发给系统管理员/开发定位。

从源头修复(给开发/运维)

  • 捕获并自动重试:对错误码 1213(或 SQLSTATE 40001)做指数退避重试 3–5 次,这是处理并发写入的标准做法。

  • 统一加锁顺序:所有相关事务按相同顺序访问表/行(例如先父表再子表、先项目再明细),减少循环等待的机会。

  • 缩短事务:只把必要语句放进事务;尽早提交,避免在事务内做耗时逻辑/网络调用。

  • 补齐和优化索引

    • 为外键列(如 SubjectId/TemplateSheetId/CreatedSheetId/ProjectId)建索引,降低外键校验锁范围。

    • 为参与唯一/查重的字段(如 UUID/UNIQUEID)确认存在高选择性的索引。

  • 降低隔离级别(仅在可接受的一致性前提下):从 REPEATABLE-READ 调整为 READ COMMITTED,减少 Next-Key/GAP 锁带来的冲突。

  • 避免大范围扫描:改写校验/查重语句,使用等值匹配;必要时把写入拆批。

  • 排查死锁链:在故障发生后立刻抓取

    • SHOW ENGINE INNODB STATUS\G(最新死锁栈)

    • INFORMATION_SCHEMA.INNODB_TRX/INNODB_LOCKS/INNODB_LOCK_WAITSsys.innodb_lock_waits
      看看涉及的两条语句、锁的对象和索引,针对性调整。

  • 幂等设计:如果是“复制/创建”类操作,加入业务幂等键(如 UNIQUEID),并使用 INSERT … ON DUPLICATE KEY UPDATE 或先查再插,配合重试更安全。

小结

这不是 Excel 本身的问题,而是后台数据库在高并发下插入时发生的死锁
短期:重试即可;长期:加重试、统一锁序、补索引、缩短事务,并用死锁日志定位具体冲突点。