讲师中心 微信公众号
AI工具推荐 视频效率加速

TP5.1 数据库死锁频发?调整事务隔离级别并缩短事务执行时间

陌杰大大_5912

陌杰大大_5912

发布时间:2026-07-07 21:22:27

|

174人浏览过

|

来源于php中文网

原创

TP5.1项目死锁源于REPEATABLE READ下的间隙锁与长事务,应切换为READ COMMITTED隔离级别、压缩事务边界、移除非DB操作、拆分事务、设置锁等待超时并实现死锁自动重试。

tp5.1 数据库死锁频发?调整事务隔离级别并缩短事务执行时间

TP5.1项目中频繁报错“Deadlock found when trying to get lock”,接口偶发失败、订单状态不一致、库存扣减丢失,根本原因是InnoDB在REPEATABLE READ隔离级别下触发间隙锁+事务执行时间过长,导致多个并发请求互相等待同一组索引资源。

确认当前隔离级别并切换为READ COMMITTED

进入MySQL命令行,执行:SELECT @@transaction_isolation; → 查看返回值是否为REPEATABLE-READ。

若确认是REPEATABLE READ,立即在TP5.1数据库配置文件config/database.php中修改:'params' => ['charset' => 'utf8mb4', 'options' => [\PDO::ATTR_CASE => \PDO::CASE_NATURAL, \PDO::MYSQL_ATTR_INIT_COMMAND => "SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"]]。

【必须重启PHP-FPM或Web服务器进程,否则新隔离级别不会生效】

READ COMMITTED能消除间隙锁(Gap Lock),大幅降低因范围查询引发的死锁概率——比如WHERE status = 0 AND created_at > '2026-07-01'这类条件不再锁定索引间隙。

定位并压缩事务边界

第一步:打开TP5.1的SQL日志,在config/database.php中设置'debug' => true,复现一次死锁请求,从runtime/log下找到对应SQL执行序列。

第二步:检查事务块内是否混入非DB操作——例如调用第三方HTTP接口、生成PDF、写本地文件、复杂循环计算。这些操作必须全部移出Db::transaction()包裹范围。

第三步:将原本一个事务内完成的“查库存→扣减→写日志→发MQ”拆成两个独立事务:前两步为一个短事务(

ThinkPHP5.1企业站点快速开发-源码课件
ThinkPHP5.1企业站点快速开发-源码课件

ThinkPHP5.1企业站点快速开发

下载

这一步不做,哪怕隔离级别调低,只要事务内含sleep(1)或file_get_contents(),锁就一直挂着,死锁概率不降反升。

强制统一SQL访问顺序(方法一:代码层硬约束)

方法一:在模型类中定义静态锁序规则。例如订单与库存关联场景,所有涉及order和stock表的操作,必须严格按order → stock顺序执行UPDATE。

方法二:对共用资源加应用层分布式锁。使用Redis SETNX指令,在事务开始前获取lock:order_stock_sync,超时设为3秒,未获取到则直接返回重试提示,避免进入数据库锁竞争。

方法三:改写SQL,用单条语句替代多步更新。例如原逻辑UPDATE stock SET num = num - 1 WHERE id = 123; UPDATE order SET status = 2 WHERE id = 456;,合并为UPDATE stock s JOIN order o ON s.goods_id = o.goods_id SET s.num = s.num - 1, o.status = 2 WHERE s.id = 123 AND o.id = 456;——单语句只持有一把锁,彻底规避交叉等待。

【TP5.1默认不支持跨表JOIN更新,此方法需手动使用Db::execute()执行原生SQL】

设置锁等待超时并启用自动重试

在config/database.php的params数组中追加:\PDO::MYSQL_ATTR_INIT_COMMAND => "SET SESSION innodb_lock_wait_timeout = 10",将锁等待上限从默认50秒压至10秒。

在业务逻辑中捕获异常:try { Db::transaction(function () { ... }); } catch (\PDOException $e) { if ($e->getCode() == '40001' || strpos($e->getMessage(), 'Deadlock') !== false) { usleep(rand(10000, 50000)); // 随机延迟10~50ms retry(); } }。

这一步必须做——InnoDB检测到死锁后会回滚事务并抛出错误码40001,不重试等于主动放弃请求。

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

相关专题

更多
数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

2745

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

3941

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

3031

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

967

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

2667

2023.10.09

数据库对象名无效怎么解决
数据库对象名无效怎么解决

数据库对象名无效解决办法:1、检查使用的对象名是否正确,确保没有拼写错误;2、检查数据库中是否已存在具有相同名称的对象,如果是,请更改对象名为一个不同的名称,然后重新创建;3、确保在连接数据库时使用了正确的用户名、密码和数据库名称;4、尝试重启数据库服务,然后再次尝试创建或使用对象;5、尝试更新驱动程序,然后再次尝试创建或使用对象。

2667

2023.10.16

vb连接access数据库的方法
vb连接access数据库的方法

vb连接access数据库方法:1、使用ADO连接,首先导入System.Data.OleDb模块,然后定义一个连接字符串,接着创建一个OleDbConnection对象并使用Open() 方法打开连接;2、使用DAO连接,首先导入 Microsoft.Jet.OLEDB模块,然后定义一个连接字符串,接着创建一个JetConnection对象并使用Open()方法打开连接即可。

2893

2023.10.16

vb连接数据库的方法
vb连接数据库的方法

vb连接数据库的方法有使用ADO对象库、使用OLEDB数据提供程序、使用ODBC数据源等。详细介绍:1、使用ADO对象库方法,ADO是一种用于访问数据库的COM组件,可以通过ADO连接数据库并执行SQL语句。可以使用ADODB.Connection对象来建立与数据库的连接,然后使用ADODB.Recordset对象来执行查询和操作数据;2、使用OLEDB数据提供程序方法等等。

2481

2023.10.19

OpenJDK JVM参数怎么调优
OpenJDK JVM参数怎么调优

Java应用运行缓慢,如何调整JVM参数?本专题介绍OpenJDK JVM性能调优的基本流程,涵盖性能指标确认、运行数据采集、内存配置和垃圾回收分析,帮助你先定位瓶颈,再通过对照测试验证效果,避免直接套用参数而影响应用稳定性。

100

2026.10.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
ThinkPHP5.1企业站点快速开发
ThinkPHP5.1企业站点快速开发

共30课时 | 6.4万人学习

TP5.1博客后台视频教程
TP5.1博客后台视频教程

共8课时 | 1.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn