Как объект PHP PDO может вычислить, если он уже находится в транзакции MySQL?
У меня есть два сложных PHP-объекта, каждый из которых имеет данные в нескольких таблицах MySQL.
Иногда мне просто нужно удалить один объект A из базы данных, и для этого требуется 3 инструкции SQL.
Иногда мне нужно удалить один объект B Из базы данных, который принимает 4 оператора SQL, и который также должен найти и удалить все объекты A, которыми владеет объект B.
Таким образом, внутри функции delete_A () я выполняю эти инструкции внутри транзакции. Внутри функции delete_B () я хочу запустить одну большую транзакцию, которая охватывает действия внутри delete_A (). Если весь атом удаления A B терпит неудачу, мне нужно восстановить все его A в откате.
Как обновить определение delete_A (), чтобы открыть только новую транзакцию , Если уже не выполняется более крупная транзакция.
Я ожидал, что смогу сделать что-то подобное, но атрибут autocommit, похоже, не изменяется beginTransaction()
function delete_A($a){
global $pdo;
$already_in_transaction = !$pdo->getAttribute(PDO::ATTR_AUTOCOMMIT);
if(!$already_in_transaction){
$pdo->beginTransaction();
}
//Delete the A
if(!$already_in_transaction){
$pdo->commit();
}
}
function delete_B($b){
global $pdo;
$pdo->beginTransaction();
foreach($list_of_As as $a){
delete_A($a);
}
$pdo->commit();
}
3 ответов:
PDO::ATTR_AUTOCOMMITэто не атрибут индикатора, это атрибут управления. Он определяет, будут ли операторы SQL неявно фиксироваться, когда они завершатся.Вы можете вызвать
PDO::inTransaction(), который возвращает0, Если у вас нет незавершенной транзакции, и1, Если у вас есть незавершенная транзакция, которую необходимо зафиксировать или откатить. Однако эта функция не задокументирована, поэтому трудно сказать, безопасно ли полагаться на то, что она присутствует во всех будущих версиях PDO.Я рекомендую использовать PHP разработчики не пытаются управлять транзакциями в рамках функций или классов. Вы должны управлять транзакциями на верхнем уровне приложения.
См. также:
В итоге я просто использовал исключение, вызванное
->beginTransaction(), чтобы выяснить, был ли я в транзакции, и с его помощью решить, следует ли фиксировать во внутреннем цикле. Так чтоdelete_A()в итоге выглядело так:function delete_A($a){ global $pdo; try { $pdo->beginTransaction(); } catch (PDOException $e) { $already_in_transaction = true; } //Delete the A if(!$already_in_transaction){ $pdo->commit(); } }И
delete_B()работает без изменений.
Один из способов-создать свой собственный класс PDOConnect, который имеет переменную
Это было бы моим предпочтением. Конечно, этот пример потребует настройки и переодевания и т. д., Но он должен быть хорошим фундаментом для начала.$hasTransaction. Тогда ты просто проверь это. Пример можно найти в комментариях функции beginTransaction на php.net здесь http://www.php.net/manual/en/pdo.begintransaction.php#81022Боковое Примечание помните, что ваш стол должен быть INNODB для сделки, чтобы работать. И так как вы должны быть в INNODB для транзакций, чтобы работать, вы должны принять Совет prodigitalson и использовать ограничения внешнего ключа.
Comments