3

次のPHPコードがあります。

$dbh->beginTransaction();
$dbh->exec("LOCK TABLES
    `reservations` WRITE, `settings` WRITE");
$dbh->exec("CREATE TEMPORARY TABLE
        temp_reservations
    SELECT * FROM reservations");
$dbh->exec("ALTER TABLE
        `temp_reservations`
    ADD INDEX ( conf_num ) ; ");

// [...Other stuff here with temp_reservations...]

$dbh->exec("DELETE QUICK FROM `reservations`");
$dbh->exec("OPTIMIZE TABLE `reservations`");
$dbh->exec("INSERT INTO `reservations` SELECT * FROM temp_reservations");

var_dump(GlobalContainer::$dbh->inTransaction()); // true
$dbh->exec("UNLOCK TABLES");
$dbh->rollBack();

トランザクションは通常の更新/挿入では正常に機能していますが、上記のコードは何らかの理由で機能していません。上記のエラーが発生すると、完全に空のreservationsテーブルが残ります。PDO::beginTransactionページで、「MySQL を含む一部のデータベースは、DROP TABLE や CREATE TABLE などのデータベース定義言語 (DDL) ステートメントがトランザクション内で発行されると、暗黙的な COMMIT を自動的に発行する」と読みました。MySQLのマニュアルには「データ定義ステートメント」のリストがあります。これは、上記のリストのDDLと同じであると想定していますCREATE TABLEが、一時テーブルを作成しているだけです。これを回避する方法はありますか?

また、空のテーブルが残っているという事実は、クエリのreservationsにコミットが発生したことを示していますか?DELETE QUICK FROM reservations

編集:追加のメモとして、このINSERT INTO reservations行は次のエラーも生成します:

バッファリングされていない他のクエリがアクティブな間は、クエリを実行できません。PDOStatement::fetchAll() の使用を検討してください。または、コードが mysql に対してのみ実行される場合は、PDO::MYSQL_ATTR_USE_BUFFERED_QUERY 属性を設定して、クエリのバッファリングを有効にすることができます。

やってみ$dbh->setAttribute( PDO::MYSQL_ATTR_USE_BUFFERED_QUERY , true);ましたが、影響はないようです。取引に何らかの関係があると推測していますが、よくわかりません。このエラーの原因を正確に特定できる人はいますか?

4

1 に答える 1

2

あなたのOPTIMIZE TABLEステートメントは暗黙的なコミットを引き起こしています。

何をしようとしているのか正確にはわかりませんが、コードを次のように短縮できるようです。

$dbh->exec("OPTIMIZE TABLE `reservations`");

他のすべてのコードは、仕事をより複雑にするだけで、何のメリットもありません。

また、MyISAM テーブルはトランザクションをサポートしないため、InnoDB テーブルを使用していると仮定しています。MyISAM テーブルに対するすべての DDL または DML 操作は、暗黙的に即座にコミットされます。

ところで、バッファリングされたクエリはトランザクションとは何の関係もありません。SELECT の結果セットを一度に 1 行ずつフェッチするのに対し、PHP では結果セット全体をメモリにフェッチしてから反復処理する必要があります。説明を参照してください: http://php.net/manual/en/mysqlinfo.concepts.buffering.php

于 2013-01-29T01:57:51.447 に答える