使用commit()时是否需调用save()?关于重复数据库事务的咨询
哥们,咱先把这事掰扯清楚——在你当前的代码逻辑里,其实不需要在调用commit()前纠结要不要save(),但得看你是想把用户更新和团队插入做成原子操作,还是分开独立执行。下面给你详细拆解:
核心结论先给你
在多数ORM(包括F3的DB类)里,save()本身就会触发INSERT/UPDATE操作,默认是自动提交事务的;而commit()是用来确认你手动开启的事务的。两者作用场景不一样,不存在“重复执行相同事务”的情况,但你得搞清楚事务的范围。
针对你代码的具体分析
你现在的代码逻辑是:
if (isset($userId)) { $update = true; $user->load(array('id=:id', array(':id' => $userId))); } $user->designation_id = $f3->get('POST.designation_id'); $user->firstname = $f3->get('POST.firstname'); $user->lastname = $f3->get('POST.lastname'); $user->save(); // 更新users表 $this->db->begin(); foreach ($userTeams as $teamId) { $sqlArray[] = sprintf('INSERT INTO ...'); // 执行插入逻辑 } $this->db->commit();
这里的$user->save()是独立的事务,执行完就自动提交了;后面的begin()和commit()是包裹团队插入的另一个独立事务。这时候两者是分开的,不存在重复,但如果想让“用户更新”和“团队插入”要么都成功要么都失败(原子操作),你得调整代码结构。
正确的事务包裹写法
如果要把这两个操作放在同一个事务里,应该先开启事务,再执行所有操作,最后统一提交:
$this->db->begin(); try { // 加载或创建用户 if (isset($userId)) { $update = true; $user->load(array('id=:id', array(':id' => $userId))); } // 赋值并保存用户 $user->designation_id = $f3->get('POST.designation_id'); $user->firstname = $f3->get('POST.firstname'); $user->lastname = $f3->get('POST.lastname'); $user->save(); // 因为事务已开启,此时不会自动提交 // 批量插入团队关联 foreach ($userTeams as $teamId) { $sql = sprintf('INSERT INTO user_teams (user_id, team_id) VALUES (%d, %d)', $user->id, $teamId); $this->db->exec($sql); } // 统一提交整个事务 $this->db->commit(); } catch (Exception $e) { // 出错就回滚所有操作 $this->db->rollback(); // 这里可以加错误日志或者给用户提示 }
再明确几个关键点
- 如果你不需要原子操作,
$user->save()单独执行就够了,它会自动提交,不需要额外调用commit(); - 如果你手动开启了事务(
begin()),那么在事务里的所有DB操作(包括save())都不会自动提交,必须调用commit()才能把所有操作一起提交; - 单独调用
commit()而没有先开启事务,其实不会有任何效果,因为没有未提交的事务需要确认。
内容的提问来源于stack exchange,提问作者Azima
相关产品推荐
相关产品推荐

