2010-07-26 7 views
6

Я думаю, что сам вопрос довольно понятен. Код приведен ниже -Зачем совершается следующая транзакция PDO?

<?php 
    $PDO = NULL; 
    $pdo_dsn = 'mysql:host=localhost;dbname=pdo_test'; 
    $pdo_persistence = array(PDO::ATTR_PERSISTENT => true); 
    $db_user = 'root'; 
    $db_pass = ''; 
    $db_query = "INSERT INTO person(name, address) 
        VALUES ('Mamsi Mamsi', 'Katabon')"; 

    try 
    { 
      $PDO = new PDO($pdo_dsn, $db_user, $db_pass, 
           $pdo_persistence); 
    } 
    catch(PDOException $e) 
    { 
      echo "Error occured: ". $e->getMessage(); 
      die(); 
    } 

    $PDO->setAttribute(PDO::ATTR_ERRMODE, 
          PDO::ERRMODE_EXCEPTION); 
    $PDO->setAttribute(PDO::ATTR_AUTOCOMMIT, false); 

    try 
    { 
      $PDO->beginTransaction(); 
      $PDO->exec($db_query); 

      throw new PDOException('Generated Exception'); 

      $PDO->commit(); 
    } 
    catch(PDOException $e) 
    { 
      echo "An error occured while doing a database transaction. The 
      error message is : ".$e->getMessage(); 

      $PDO->rollBack(); 
      die(); 
    } 
?> 

Даже если я откат транзакции внутри блока улова, данные по-прежнему включены в базу данных. Зачем?

EDIT

Я добавляю следующие несколько строк из documentation для дальнейшего уточнения -

К сожалению, не каждая база данных поддерживает транзакции, поэтому PDO необходимо работать в так называемом «автоматический фиксация» при первом открытии соединения . Режим автоматической фиксации означает, что каждый запрошенный вами запрос имеет свою собственную неявную транзакцию, если база данных поддерживает ее, или нет транзакции , если база данных не поддерживает транзакции. Если вам нужна операция , вы должны использовать метод PDO :: beginTransaction() для . Если базовый драйвер не поддерживает транзакции, будет выбрано PDOException (независимо от вашей обработки ошибок : это всегда является серьезной ошибкой). Когда вы находитесь в транзакции, вы можете использовать PDO :: commit() или PDO :: rollBack(), чтобы закончить , в зависимости от успеха кода, который вы выполняете во время транзакции .

Кроме того, следующие строки из this страницы -

bool PDO::beginTransaction (void ) 

выключает режим автоматической фиксации. В то время как режим автосохранения отключен, изменений, внесенных в базу данных через экземпляр объекта PDO, не завершены до завершения транзакции, вызвав PDO :: commit(). Вызов PDO :: rollBack() откатит все изменения в базе данных и вернет соединение в режим автосохранения.

Некоторые базы данных, включая MySQL, автоматически выдавать неявное COMMIT, когда язык определения данных (DDL) заявление, такие как DROP TABLE или CREATE TABLE выдается в рамках транзакции. Недопустимый COMMIT не позволит вам отменить любые другие изменения в пределах границы транзакции.

+0

Что происходит, если вы просто откатываете транзакцию, в которой вы сейчас бросаете исключение? – Amber

+0

@Amber: не тестировал это :( –

ответ

15

Необходимо проверить, что вы используете INNODB в качестве типа своей базы данных. MyISAM не поддерживает транзакции.

+0

«Проблема» в том, что PDO должен возбуждать исключение, если вы начинаете транзакцию с помощью драйвера, который их не поддерживает. Ошибка? Docs? – cbednarski

+0

Нет подсказки. Все, что я знаю, это то, что это было проблемой для меня, когда я пытался делать транзакции с использованием PDO с драйвером MySQL, никаких исключений никогда не возникало. Может быть ошибка, мне нужно было бы прочитать документы, чтобы убедиться в этом. EDIT: Похоже, что это не ошибка: возвращает TRUE при успешном завершении или FALSE при сбое. Из man-страниц для PDO-> beginTransaction –

+0

Документы, на которые я ссылаюсь, находятся здесь: http://us2.php.net/manual/en/pdo.transactions .php – cbednarski