如何在 propel 中创建一个新的事务范围

How to create a new transaction scope in propel

我们在 mysql 数据库上使用 propel 作为 orm。 我们正在更改几个 table 并在事务期间调用外部服务。在此期间,我们将这些操作和响应记录在日志 table 中。如果发生错误,我们会恢复操作但希望保留日志消息。目前,日志消息正在使用相同的事务范围,并将随事务一起还原。

我是否通过

获得新的连接和事务范围
$con = Propel::getConnection(DATABASE_NAME);

或者我是否必须检查是否返回相同的连接

伪代码

public function write_log()
{
  $con = Propel::getConnection(DATABASE_NAME);

  $log=new Log();
  $log->message('foo');
  $log->save($con);
}

public function change_data()
{
    write_log('start');

    $con = Propel::getConnection(DATABASE_NAME);
    $con->beginTransaction();
    try {
       //this message should stay in the database
       write_log('change_db_data:'.$new_db_value);
       //this should be reverted
       change_db_data($new_db_value); 

       write_log('call webservice_1');
       $response=call_webservice_1();
       write_log($response);
       if($response==null)
       { 
         $con->rollback();
       }

       write_log('call webservice_2');
       $response=call_webservice_2();
       write_log($response);
       if($response==null)
       { 
         $con->rollback();
       }


       $con->commit();
    }
    catch(Exception $e){
        $con->rollback();
        write_log('error')
    }
    write_log('end');
}

选择 Propel 是个不错的选择。您有两种选择,要么将日志记录封装在自己的事务中,要么使用 Propel 独特支持的嵌套事务。

第一个只需要 write_log 函数中的事务性:

public function write_log()
{
  $con = Propel::getConnection(DATABASE_NAME);

  $con->beginTransaction();
  $log=new Log();
  $log->message('foo');
  $log->save($con);
  $con->commit();
}

二是开启嵌套事务,保证只回滚内层事务:

public function write_log()
{
  $con = Propel::getConnection(DATABASE_NAME);

  $log=new Log();
  $log->message('foo');
  $log->save($con);
}

public function change_data()
{
    $con = Propel::getConnection(DATABASE_NAME);
    $con->beginTransaction();
    write_log('start');

    $con->beginTransaction();
    try {
       //this message should stay in the database
       write_log('change_db_data:'.$new_db_value);
       //this should be reverted
       change_db_data($new_db_value); 

       write_log('call webservice_1');
       $response=call_webservice_1();
       write_log($response);
       if($response==null)
       { 
         throw new \Exception('Null response.');
       }

       write_log('call webservice_2');
       $response=call_webservice_2();
       write_log($response);
       if($response==null)
       { 
         throw new \Exception('Null response.');
       }

       $con->commit();
    }
    catch(Exception $e){
        $con->rollback();
        write_log('error')
    }
    write_log('end');
    $con->commit();
}