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;
        }
    }

}

?>

EDIT - クラスの使用例

$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 番目のクエリは失敗したため、成功するものはありません。

私の問題は、ロールバックしないことです。クエリの失敗に関係なく、常に行が挿入されます。

4

2 に答える 2

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 に答える
0

START TRANSACTION代わりに使ってみてくださいBEGIN

ちなみにSTART TRANSACTION、次を使用できますWITH CONSISTENT SNAPSHOT

WITH CONSISTENT SNAPSHOT オプションは、それが可能なストレージ エンジンの一貫した読み取りを開始します。これは InnoDB にのみ適用されます。

ソース: MySQL ドキュメント

于 2012-10-13T12:28:25.993 に答える