【问题标题】:transaction can't rollback in codeigniter事务无法在 codeigniter 中回滚
【发布时间】:2018-02-09 19:04:10
【问题描述】:

我正在处理事务,在提到的代码中我遇到了一些问题。我没有提交事务,但它向我的数据库中插入了数据。

$this->db->trans_begin();
$this->db->insert('tblorder',$data);
$orderid=$this->db->insert_id();
foreach ($orderItemList as $orderItemList) {
    $orderitem = array('orderid' =>$orderid ,'productid' =>$orderItemList->productid ,'amount' =>$orderItemList->amount);
    $this->db->insert('tblorderitem',$orderitem);
}
$this->db->trans_complete();

if ($this->db->trans_status() == 1) {
    $this->db->trans_rollback();
    return "true";
} else {
    $this->db->trans_commit();
    return "false";
}

我回滚了事务,并且再次将所有数据插入到我的数据库中。一定是什么问题?看不懂。

【问题讨论】:

    标签: php mysql codeigniter transactions codeigniter-3


    【解决方案1】:

    不要使用$this->db->trans_complete();

    根据documentation

    $this->db->trans_begin();
    
    $this->db->query('AN SQL QUERY...');
    $this->db->query('ANOTHER QUERY...');
    $this->db->query('AND YET ANOTHER QUERY...');
    
    if ($this->db->trans_status() === FALSE)
    {
            $this->db->trans_rollback();
    }
    else
    {
            $this->db->trans_commit();
    }
    

    【讨论】:

      【解决方案2】:

      答案已更新!

      我必须告诉你,codeigniter 的默认配置是自动提交所有事务。

      如果您出于任何原因想要禁用此功能,则必须使用此行:

      $this->db->trans_off();    
      

      之前的

      $this->db->begin();
      

      这么说,所以当你使用

      $this->db->trans_complete();
      

      您将需要提交或回滚,如下所示:

      $result = $this->db->trans_complete();
      
      if($result === true){
          $this->db->trans_commit();
      }else{
          $this->db->trans_rollback();
      }
      

      最后你想要的是:

      $this->db->trans_off();
      
      $this->db->query("insert this...");
      $this->db->query("insert that...");
      
      $result = $this->db->trans_complete();
      
      if($result === true){
          $this->db->trans_commit();
      }else{
          $this->db->trans_rollback();
      }
      

      【讨论】:

      • 我想要回滚事务而不是做什么?
      • 你对trans_off()的使用是错误的。一旦运行,其他trans_ 方法将不会执行。嗯......从技术上讲,他们执行,但一旦他们看到 trans_off() 已被调用,他们立即返回 FALSE。
      【解决方案3】:

      据我所知,对于 CI 3.0.1 版,您唯一需要担心的是将 $this->db->trans_start();$this->db->trans_complete(); 放在哪里

      所以对于这样的情况:

      $this->db->trans_start();
      //any code goes here
      $this->db->trans_complete();
      

      如果出现问题,事务将被回滚,或者将在调用时提交给$this->db->trans_complete();

      因为如果您深入了解 trans_start 方法,它包含 trans_begintrans_complete 方法包含检查 trans_status 并相应地调用 trans_committrans_rollback 方法。

      同样适用于嵌套事务:

      $this->db->trans_start();
      //any code goes here
      $this->db->trans_start();
      //any code goes here
      $this->db->trans_complete();
      //any code goes here
      $this->db->trans_complete();
      

      默认情况下,Codeigniter 以严格模式运行所有事务,因此最后 trans_complete 将全部提交,或者如果任何事情失败,则所有回滚。

      【讨论】:

        【解决方案4】:

        为什么你要ROLLBACK?是因为其他而不是虚假的trans_status?如果是这样,请致电trans_rollback致电trans_completetrans_commit

        听起来这对您的情况来说是最佳选择(对不正确的语法表示歉意):

        trans_start
        ...
        if ( some non-db problem )  trans_rollback
        trans_complete
        

        【讨论】:

          【解决方案5】:

          这样做。 如果您想了解有关交易的更多信息Check My answer on another question。这有助于您对事务有一个清晰的认识。

          $this->db->trans_begin();
          
          $this->db->insert('tblorder',$data);
          $orderid=$this->db->insert_id();
          
          $orderitem = array();
          
          foreach ($orderItemList as $orderItemList) 
          {
              $orderitem[] = array('orderid' =>$orderid ,'productid' =>$orderItemList->productid ,'amount' =>$orderItemList->amount);
          }
          
          $this->db->insert_batch('tblorderitem', $orderitem); 
          
          $this->db->trans_complete();
          
          if ($this->db->trans_status() === FALSE) 
          {
              $this->db->trans_rollback();
              return FALSE;
          } 
          else 
          {
              $this->db->trans_commit();
              return TRUE;
          }
          

          【讨论】:

            【解决方案6】:

            您编写的代码与编写自动事务的方式几乎相同 - 只是不一样。我的建议?不要试图智取 CodeIgniter,使用“自动”模式进行交易。然后,如果需要,将为您处理回滚。

            我已使用自动交易模式重做您的代码。我还从$orderItemList 收集数据,因此可以使用批处理插入数据,而不是在循环中重复调用db->insert

            $this->db->trans_start();
            $this->db->insert('tblorder', $data);
            $orderid = $this->db->insert_id();
            foreach($orderItemList as $orderItem)
            {
                $orderedItems[] = [
                  'orderid' => $orderid,
                  'productid' => $orderItem->productid,
                  'amount' => $orderItem->amount
                ];
            }
            if(isset($orderedItems))
            {
                $this->db->insert_batch('tblorderitem', $orderedItems);
            }
            $this->db->trans_complete();
            $this->db->trans_status();
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多