Часть транзакции MySql, выполняемая без "commit" - PullRequest
1 голос
/ 29 декабря 2011

У меня есть PHP-скрипт, который удаляет старые данные из базы данных, читает данные из другой, а затем вставляет новые данные в первую. По понятным причинам я хотел это использовать транзакции, с откатом на каждую возможную ошибку. Кажется, это работает, за исключением одного неожиданного и - для меня - необъяснимого поведения.

При (целенаправленном) прерывании сценария все мои операторы DELETE успешно откатываются, кроме одного, который, кажется, все равно был выполнен.

Код имеет массив «задач», каждый из которых содержит, помимо прочего, имя таблицы, удобочитаемое описание типа данных и конкретный оператор SELECT для исходной базы данных. Вот фрагмент этого массива «рабочий список»:

$worklist = array(
        array(
            "table" => "campaign",
            "description" => "campaign details",
            "selectsql" => "SELECT ... "
        ),
        array(
            "table" => "product",
            "description" => "product",
        "selectsql" => "SELECT ... "
    ),
    ...
        array(
            "table" => "context_search",
        "description" => "product details for search",
        "selectsql" => "SELECT ... "
    )
);

После определения этого «рабочего списка» я начинаю свою транзакцию следующим образом:

$dbfront = new PDO(...);
$dbfront->exec("SET AUTOCOMMIT = 0");
$dbfront->beginTransaction();
$dbfront->exec("SET FOREIGN_KEY_CHECKS=0");

После чего я перебираю рабочий список для удаления старых данных следующим образом:

        foreach($worklist as $job){
            $deleter = $dbfront->prepare("DELETE FROM "
                                    . $job["table"] .
                                " WHERE
                                    campaign_id = " . $campaign_id .
                                ";");
            try{
                $deleter->execute();
                echo $deleter->rowCount() . "lines of old data deleted from " . $job["table"] . " table\n"; 
            } catch (exception $e){
                echo $e . "\n";
                $dbfront->rollBack();
                echo "An error occurred. All changes have been rolled back.\n";
                exit;
            }
        }

Затем, есть код для выбора новых данных из другой базы данных и вставки их в 'dbfront', а затем, в конце, у меня есть эта часть, чтобы зафиксировать изменения:

try {
    $dbfront->commit();
    echo "\nAll changes committed\n";
} catch (Exception $e) {
    echo $e . "\n";
    $dbfront->rollBack();
    echo "An error occurred. All changes have been rolled back.\n";
    exit;
}

Кто-нибудь знает, что может быть правдоподобным объяснением того, что первые две таблицы будут полностью откатываться, когда я наполовину прерываю этот сценарий, а третья должна выполняться, несмотря ни на что?

1 Ответ

2 голосов
/ 29 декабря 2011

Не все механизмы хранения в MySQL поддерживают транзакции.Если транзакция работает с таблицей MyISAM, изменения в этой таблице будут зафиксированы независимо от того, была ли зафиксирована или отменена оставшаяся часть транзакции.

...