2012-10-13 34 views
0

我前段時間寫過一個數據庫類,我在大多數項目中使用它,最近擴展了類來處理事務。PHP mysql_query事務沒有回滾

下面的Transaction類似乎沒有正常工作,服務器是MySQL innoDB,並且我檢查了事務對我的數據庫(使用PHPMyAdmin)有效。所以這顯然是我的代碼錯誤或我的誤解。

<?php 

/** 
* Description of Database 
* 
* @author http://stackoverflow.com/users/820750/gerve 
*/ 
class Database { 

    private $connection; 

    public function __construct($dbServer, $dbName, $dbUser, $dbPassword) { 
     $this->connection = mysql_connect($dbServer, $dbUser, $dbPassword); 
     mysql_select_db($dbName, $this->connection); 
    } 

    public function query($query, $die = true) { 
     return new Query($query, $this->connection, $die); 
    } 

    public function escape($param) { 
     return mysql_real_escape_string($param, $this->connection); 
    } 

    public function transaction() { 
     return new Transaction($this->connection); 
    } 

} 

class Query { 

    private $query; 
    public $count; 
    public $countModified; 
    public $queryString; 


    public function __construct($query, $link_identifier, $die = true) { 
     if($die){ 
      $this->query = mysql_query($query, $link_identifier) or die(mysql_error()); 
     } 
     else{ 
      $this->query = mysql_query($query, $link_identifier); 
     } 

     $this->count = is_resource($this->query) ? mysql_num_rows($this->query) : 0; 
     $this->countModified = mysql_affected_rows($link_identifier); 

     $this->queryString = $query; 
    } 

    public function nextRow() { 
     return mysql_fetch_object($this->query); 
    } 

    public function allRows() { 
     $array = array(); 

     while($row = mysql_fetch_object($this->query)){ 
      $array[] = $row; 
     } 

     return $row; 
    } 

} 

class Transaction { 

    private $connection; 
    private $isAlive; 

    public function __construct($link_identifier) { 
     $this->connection = $link_identifier; 
     $this->query("BEGIN"); 
     $this->isAlive = true; 
    } 

    public function query($query) { 
     if($this->isAlive){ 
      $q = new Query($query, $this->connection, false); 
      if(mysql_error()){ 
       $this->rollBack(); 
       return false; 
      } 
      else{ 
       return $q; 
      } 
     } 
    } 

    public function rollBack() { 
     if($this->isAlive){ 
      $this->query("ROLLBACK"); 
      $this->isAlive = false; 
     } 
    } 

    public function commit() { 
     if($this->isAlive){ 
      $this->query("COMMIT"); 
      $this->isAlive = false; 
      return true; 
     } 
     else{ 
      return false; 
     } 
    } 

} 

?> 

編輯 - 類

$DB = new Database(dbServer, dbName, dbUser, dbPassword); 
$transaction = $DB->transaction(); 

$transaction->query("INSERT INTO myTable `c1`, `c2` VALUES('1', '2')"); //Works 
$transaction->query("INSERT INTO jhsdjkag 5dafa 545"); //Fails 
$transaction->query("INSERT INTO myTable2 `c1`, `c2` VALUES('3', '4')"); //Works 

$transaction->commit(); 

實施例使用上面的代碼不應該插入任何行到數據庫中,所述第二查詢失敗所以沒有應該成功。

我的問題是它不會回滾,總是插入行而不管失敗的查詢。

+0

請不要在新代碼中使用'mysql_ *'函數。他們不再被維護,社區已經開始[棄用流程](http://goo.gl/KJveJ)。請參閱[**紅框**](http://goo.gl/GPmFd)?相反,您應該瞭解[準備好的語句](http://goo.gl/vn8zQ)並使用[PDO](http://php.net/pdo)或[MySQLi](http://php.net/ mysqli的)。如果你不能決定,[本文](http://goo.gl/3gqF9)將有助於選擇。如果你關心學習,[這是一本很好的PDO教程](http://goo.gl/vFWnC)。 – PeeHaa

+0

I.e.只是使用默認支持事務的東西,並且仍然是受支持的功能。 – PeeHaa

+0

@PeeHaa:謝謝,會考慮PDO。但我現在仍然想要修復這個問題。 – Drahcir

回答

0

我發現有在代碼中的錯誤,只需在__construct()。這是非常簡單的,我剛換1號線:

FROM:

public function __construct($link_identifier) { 
    $this->connection = $link_identifier; 
    $this->query("BEGIN"); 
    $this->isAlive = true; 
} 

TO:

public function __construct($link_identifier) { 
    $this->connection = $link_identifier; 
    $this->isAlive = true; 
    $this->query("BEGIN"); 
} 

- >的IsAlive正在第一 「BEGIN」 查詢後成立,這意味着BEGIN從未被髮送過。

0

嘗試使用START TRANSACTION代替BEGIN

的方式START TRANSACTION將允許您使用WITH CONSISTENT SNAPSHOT

的一致快照選項存儲引擎是能夠啓動一個consistent read。這僅適用於InnoDB。

源:MySQL Documentation