PHP mysql_query事务没有回滚

时间:2012-10-13 12:21:52

标签: php mysql transactions

我之前写过一个数据库类,我在大多数项目中使用它,最近扩展了类以处理事务。

下面的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();

上面的代码不应该在数据库中插入任何行,第二个查询失败,所以没有任何行应该成功。

我的问题是它不会回滚,无论查询失败,都会插入行。

2 个答案:

答案 0 :(得分:0)

尝试使用START TRANSACTION代替BEGIN

START TRANSACTION允许您使用WITH CONSISTENT SNAPSHOT

  

WITH CONSISTENT SNAPSHOT选项为能够使用它的存储引擎启动consistent read。这仅适用于InnoDB。

来源:MySQL Documentation

答案 1 :(得分:0)

我发现代码中存在错误,只是在__construct()中。这很简单,我只改了1行:

发件人:

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

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

- &gt;在第一个“BEGIN”查询后设置isAlive,这意味着从未发送过BEGIN。