PHP7.3操作Firebird数据库时同一事务执行多查询的范围问题
Firebird 事务处理问题解答
核心问题结论
你完全可以在主函数开头开启事务,待所有关联操作全部执行成功后再在主函数结尾提交事务,这恰恰是实现「任意操作失败、所有已执行操作全部回滚」需求的正确方案。绝对不要为每个查询单独开启事务,单独开启事务的话每个查询执行完就会独立提交,前面成功的操作根本无法回滚,完全不符合你的业务要求。
你现有代码的问题
- 子函数
insert_new_job无法访问主函数中定义的$trans事务对象,当前代码里子函数的$trans属于未定义变量,查询必然执行失败,你需要把事务对象作为参数传入子函数。 - 缺少执行失败的判断和回滚逻辑,当前代码不管某个查询是否报错,都会走到最后的提交逻辑,无法实现失败回滚的效果。
- 示例代码中
insert_new_job内的SQL有拼写错误,INSER少了字母T,应为INSERT。
修正后的示例代码
public function Main_function() { $id = $this->create_user_id(); $connection = ibase_connect($this->_db, $this->_username, $this->_password, '100'); // 开启全局事务 $trans = ibase_trans($connection, IBASE_READ+IBASE_COMMITTED+IBASE_REC_NO_VERSION); $query = "INSERT INTO USERS (user_id, name) VALUES ('john', '$id')"; $newuser = ibase_query($trans, $query); // 执行失败直接回滚 if (!$newuser) { ibase_rollback($trans); ibase_close($connection); return false; } // 把事务对象传给子函数 $jobResult = $this->insert_new_job($id, $trans); if (!$jobResult) { ibase_rollback($trans); ibase_close($connection); return false; } // 全部操作成功再提交 ibase_commit($trans); ibase_close($connection); return true; } public function create_user_id() { $id = '2'; return $id; } // 新增事务参数接收 public function insert_new_job($id, $trans) { $query = "INSERT INTO jobs (name, id, job) VALUES ('john',$id,'developer')"; $result = ibase_query($trans, $query); return $result; }
注意事项
- 只要你没有主动调用
ibase_commit或者ibase_rollback,开启的事务就一直处于激活状态,所有绑定该事务的查询都会纳入同一个事务管理范围。 - 如果后续你还要在子函数中调用其他执行查询的方法,直接把事务对象透传即可,不需要再新开事务。
内容的提问来源于stack exchange,提问作者BRABO
相关产品推荐
相关产品推荐

