Php 虽然我喜欢这个词,但这个词很愚蠢
我有这样一种情况:我有可能被非我编写的模块调用的事件处理程序函数。我的事件处理程序在数据库中创建了很多记录。如果有什么东西没有正确通过,或是丢失了,或是有什么东西出了问题,那么我肯定需要回退。我不知道触发事件处理程序的外部模块的代码是否正在处理db事务,因为代码是由其他人编写的。我还没有找到查询数据库以查看事务是否正在进行的方法 所以我会数一数。我使用的是CodeIgniter,如果我要求它开始使用嵌套的db事务(例如多次调用它的trans_start()方法),它似乎会做一些奇怪的事情。换句话说,我不能只在事件处理程序中包含trans_start(),因为如果外部函数也在使用trans_start(),则回滚和提交不会正确发生。总有一种可能,我还没有找到正确管理这些功能的方法,但我已经运行了许多测试 我的事件处理程序需要知道的是,另一个调用的模块是否已经启动了db事务?如果是这样,它不会启动另一个新事务,也不会执行任何回滚或提交。它确实相信,如果某个外部函数启动了db事务,那么它也将处理回滚/提交 我为CodeIgniter的事务方法提供了包装函数,这些函数递增/递减计数器Php 虽然我喜欢这个词,但这个词很愚蠢,php,mysql,zend-framework,transactions,pdo,Php,Mysql,Zend Framework,Transactions,Pdo,我有这样一种情况:我有可能被非我编写的模块调用的事件处理程序函数。我的事件处理程序在数据库中创建了很多记录。如果有什么东西没有正确通过,或是丢失了,或是有什么东西出了问题,那么我肯定需要回退。我不知道触发事件处理程序的外部模块的代码是否正在处理db事务,因为代码是由其他人编写的。我还没有找到查询数据库以查看事务是否正在进行的方法 所以我会数一数。我使用的是CodeIgniter,如果我要求它开始使用嵌套的db事务(例如多次调用它的trans_start()方法),它似乎会做一些奇怪的事情。换句话
function transBegin(){
//increment our number of levels
$this->_transBegin += 1;
//if we are only one level deep, we can create transaction
if($this->_transBegin ==1) {
$this->db->trans_begin();
}
}
function transCommit(){
if($this->_transBegin == 1) {
//if we are only one level deep, we can commit transaction
$this->db->trans_commit();
}
//decrement our number of levels
$this->_transBegin -= 1;
}
function transRollback(){
if($this->_transBegin == 1) {
//if we are only one level deep, we can roll back transaction
$this->db->trans_rollback();
}
//decrement our number of levels
$this->_transBegin -= 1;
}
在我的情况下,这是检查现有db事务的唯一方法。它是有效的。我不会说“应用程序正在管理db事务”。在这种情况下,这是不真实的。它只是检查应用程序的某些其他部分是否启动了任何db事务,以便避免创建嵌套的db事务。这个讨论相当古老。正如一些人所指出的,您可以在应用程序中实现这一点。PHP从版本5 > = 5.3.3有一个方法来知道您是否处于事务的中间。PDP::inTransaction()返回true或false。Link也许您可以尝试PDO::inTransaction…如果事务当前处于活动状态,则返回TRUE,否则返回FALSE。
我还没有测试过自己,但似乎还不错 似乎那个问题在他们的追踪器里消失了…:(所有采埃孚问题均表示“在下一个次要版本中修复”我希望他们有充分的理由这样做,因为这会误导很多人,并给很多人带来困惑。在我通过mysql客户端进行的测试中,
SELECT@@autocommit;
在事务处理过程中仍然返回1。这的确是一个非常好的功能。我想知道它存在于Hibernate或任何类似的更成熟的持久性层中…Prope有这个,但我仍然认为它是一个伪造的设计。请参阅我上面的编辑。回到这个主题…例如JPA有TransactionManager的概念,对于ZF来说,类似的概念是合乎逻辑的吗?我不能对JPA说,但Java不是PHP,反之亦然。PHP假设请求建立了一个工作单元,因此PHP应用程序中事务的作用域应该与请求的作用域相同。这很简单。没有PHP应用程序服务器,因此没有“对话”事务的作用域。因此,不需要让域模型类或DAO类管理事务——只需在控制器级别执行即可。@Pacerier,我不知道什么是“bdbaft”意思是。也许框架的DB层没有封装这个检查事务状态的PDO方法。我和你的答案是一样的,在我看到你的答案之前,我几乎发布了我的答案。
wrapper.php:
try {
// start transaction
include("your_script.php");
// commit transaction
} catch (RollbackException $e) {
// roll back transaction
}
try {
Zend_Registry::get('database')->beginTransaction();
}
catch (Exception $e) { }
try {
$totals = self::calculateTotals($Cart);
$PaymentInstrument = new PaymentInstrument;
$PaymentInstrument->create();
$PaymentInstrument->validate();
$PaymentInstrument->save();
Zend_Registry::get('database')->commit();
return true;
}
catch (Zend_Exception $e) {
Bootstrap::$Log->err($e->getMessage());
Zend_Registry::get('database')->rollBack();
return false;
}
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
function transBegin(){
//increment our number of levels
$this->_transBegin += 1;
//if we are only one level deep, we can create transaction
if($this->_transBegin ==1) {
$this->db->trans_begin();
}
}
function transCommit(){
if($this->_transBegin == 1) {
//if we are only one level deep, we can commit transaction
$this->db->trans_commit();
}
//decrement our number of levels
$this->_transBegin -= 1;
}
function transRollback(){
if($this->_transBegin == 1) {
//if we are only one level deep, we can roll back transaction
$this->db->trans_rollback();
}
//decrement our number of levels
$this->_transBegin -= 1;
}