在ThinkPHP中使用数据库事务需通过startTrans()开启、commit()提交、rollback()回滚,确保数据一致性。示例代码展示扣减库存与创建订单在事务中的执行,推荐使用Db::transaction()闭包方式简化操作,避免跨连接或非InnoDB引擎导致事务失效,并通过异常捕获和日志调试保障事务正确性。
在ThinkPHP中使用数据库事务,关键在于确保多个数据库操作要么全部成功,要么全部回滚,保持数据一致性。尤其在处理订单、支付、库存等业务场景时,事务的正确使用至关重要。
开启事务的基本流程
ThinkPHP提供了简洁的事务控制方法,主要通过startTrans()、commit()和rollback()三个方法来管理事务。
- startTrans():开启事务,后续操作将处于事务环境中
- commit():提交事务,所有操作生效
- rollback():回滚事务,撤销所有未提交的操作
示例代码:
$db = Db::name(‘user’);
try {
$db->startTrans();
// 扣减库存
 >$db->where(‘id’, 1)->setDec(‘stock’, 1);
// 创建订单
 >Db::name(‘order’)->insert([‘user_id’ => 1, ‘goods_id’ => 10]);
// 提交事务
 >$db->commit();
} catch (Exception $e) {
 >$db->rollback();
 >// 记录错误或抛出异常
 >throw $e;
}
使用事务的注意事项
实际开发中容易忽略一些细节,导致事务失效或资源占用。
立即学习“PHP免费学习笔记(深入)”;
- 同一个事务中涉及多个模型操作时,应使用同一个数据库连接实例,避免跨连接事务失效
- 建议用Db::transaction()闭包方式简化写法,自动处理提交与回滚
- 事务中尽量避免长时间操作(如远程请求),防止锁表时间过长
- 事务不支持跨数据库或跨连接操作,需确保所有操作在同一连接上执行
推荐使用闭包方式:
Db::transaction(function () {
 >Db::name(‘account’)->where(‘id’, 1)->setDec(‘money’, 100);
 >Db::name(‘log’)->insert([‘action’ => ‘pay’, ‘amount’ => 100]);
});
如果闭包内抛出异常,系统会自动回滚;执行成功则自动提交。
常见问题排查
事务没生效?可能是以下原因:
- 使用的数据库引擎是MyISAM,不支持事务,应改为InnoDB
- 代码中缺少异常捕获,导致rollback()未被调用
- 多个Db::name()调用未共用实例,事务状态丢失
- SQL语法错误导致语句未执行,但程序继续往下走
建议在事务操作前后加入日志,便于调试。
基本上就这些。掌握好开启、提交、回滚的时机,配合try-catch或闭包写法,就能在ThinkPHP中安全使用事务。
php thinkphp go 常见问题 sql thinkphp try throw catch 闭包 function 数据库