Транзакции и автоматическая фиксация PHP PDO
Справочное руководство по PHP PDO
Теперь, когда вы подключены через PDO, прежде чем начать выполнять запросы, вы должны сначала понять, как PDO управляет транзакциями.
Транзакции поддерживают четыре основных свойства (ACID):
- Атомарность
- Согласованность
- Изоляция
- Долговечность
Проще говоря, любая операция, выполняемая в рамках транзакции, даже если она выполняется поэтапно, гарантированно безопасно применяется к базе данных, и после фиксации другие соединения не смогут на неё повлиять.
Операции транзакции также могут быть автоматически отменены по запросу (при условии, что они ещё не были зафиксированы), что упрощает обработку ошибок в скриптах.
Обычно транзакции реализуются путём «накопления» пакета изменений и последующего одновременного их применения; преимущество этого в том, что это может значительно повысить эффективность этих изменений.
Иными словами, транзакции могут сделать скрипты быстрее и, возможно, надёжнее (хотя, чтобы получить такие преимущества, нужно правильно использовать транзакции).
К сожалению, не каждая база данных поддерживает транзакции, поэтому при первом открытии соединения PDO должен работать в так называемом режиме «автофиксации».
Режим автофиксации означает, что если база данных поддерживает транзакции, каждый выполненный запрос имеет собственную неявную транзакцию; если база данных не поддерживает транзакции, то её нет.
Если нужна транзакция, вы должны начать её с помощью метода PDO::beginTransaction(). Если базовый драйвер не поддерживает транзакции, выбрасывается PDOException (независимо от настроек обработки ошибок это серьёзное состояние ошибки).
После запуска транзакции её можно завершить с помощью PDO::commit() или PDO::rollBack() в зависимости от того, успешно ли выполнился код внутри транзакции.
Примечание:PDO проверяет только на уровне драйвера, поддерживает ли он обработку транзакций. Если из-за определённых условий выполнения транзакции недоступны, а служба базы данных принимает запрос на запуск транзакции, PDO::beginTransaction() всё равно вернёт TRUE без ошибки. Попытка использовать транзакции в таблице MyISAM базы данных MySQL — хороший пример.
Когда скрипт завершается или соединение вот-вот будет закрыто, если остаётся незавершённая транзакция, PDO автоматически откатит эту транзакцию. Эта мера безопасности помогает избежать несогласованности, когда скрипт неожиданно завершается — если транзакция не была явно зафиксирована, предполагается, что где-то произошла ошибка, поэтому выполняется откат для обеспечения сохранности данных.
Примечание:Автоматический откат может произойти только после запуска транзакции через PDO::beginTransaction(). Если вы вручную отправляете запрос на запуск транзакции, PDO не может узнать об этом и, следовательно, не может выполнить откат, когда это необходимо.
Выполнение пакетной обработки внутри транзакции:
В примере ниже предположим, что мы создаём набор записей для нового сотрудника, назначая ему ID 23. Помимо регистрации его основных данных, нам также нужно записать его зарплату.
Эти два обновления легко выполнить по отдельности, но, заключив их в вызовы PDO::beginTransaction() и PDO::commit(), вы можете гарантировать, что другие не увидят эти изменения до их завершения.
Если возникает ошибка, блок catch откатывает все изменения, сделанные с момента запуска транзакции, и выводит сообщение об ошибке.
<?php
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2',
array(PDO::ATTR_PERSISTENT => true));
echo "Connected\n";
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate)
values (23, 50000, NOW())");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
?>
Это не ограничивается внесением изменений в рамках транзакции; вы также можете выполнять сложные запросы для извлечения данных и использовать эту информацию для построения новых изменений и запросов. Когда транзакция активна, вы можете быть уверены, что другие не смогут вносить изменения, пока операция выполняется.
Другие расширения