0

前段时间我编写了一个数据库类,我将它用于大多数项目,最近扩展了该类以处理事务。

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

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

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

4

2 回答 2

0

尝试使用START TRANSACTION而不是BEGIN

顺便说一句START TRANSACTION,您可以使用WITH CONSISTENT SNAPSHOT

WITH CONSISTENT SNAPSHOT 选项为能够执行此操作的存储引擎启动一致读取。这仅适用于 InnoDB。

来源:MySQL 文档

于 2012-10-13T12:28:25.993 回答
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");
}

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

于 2012-10-17T13:23:07.180 回答