Transacciones PHP, MySQL, PDO: ¿Puede fetchAll () venir antes que commit ()?
Más preguntas de transacción!
Lo que tengo ahora es un lío de consultas encadenadas, que se invierten manualmente si falla alguna:
Bloque de código 1
$stmt1 = $db->prepare(...); // Update table1, set col=col+1
if($stmt1 = $db->execute(...)){
$stmt2 = $db->prepare(...); // Insert into table2, id=12345
if($stmt2 = $db->execute(...)){
$stmt3 = $db->prepare(...); // Select val from table3
if($stmt3 = $db->execute(...)){
$result = $stmt3->fetchAll();
if($result[0]['val'] == something){
$stmt4 = $db->prepare(...); // Update table4, set status=2
if($stmt4 = $db->execute(...)){
return true;
}else{
$stmt1 = $db->prepare(...); // Update table1, set col=col-1 (opposite of above)
$stmt1 = $db->execute(...);
$stmt2 = $db->prepare(...); // Delete from table2, where id=12345 (opposite of above)
$stmt2 = $db->execute(...);
return false;
}
}
return true;
}else{
$stmt1 = $db->prepare(...); // Update table1, set col=col-1 (opposite of above)
$stmt1 = $db->execute(...);
$stmt2 = $db->prepare(...); // Delete from table2, where id=12345 (opposite of above)
$stmt2 = $db->execute(...);
return false;
}
}else{
$stmt1 = $db->prepare(...); // Update table1, set col=col-1 (opposite of above)
$stmt1 = $db->execute(...);
return false;
}
}
Es un desastre, difícil de depurar, difícil de agregar, difícil de entender cuando las consultas son grandes, y no devolverá todas las tablas al estado original si la conexión se pierde a mitad de camino.
Este mismo proceso es aún peor al eliminar una fila, porque todo lo que necesita debe almacenarse, en caso de que la operación deba deshacerse.
Ahora sémás de esto todavía funcionará cuando lo transfiera a una sola transacción, pero la única parte de la que no estoy seguro es:
Bloque de código 2
$result = $stmt3->fetchAll();
if($result[0]['val'] == something){
... continue ...
}else{
... reverse operations ...
return false;
}
Porque la recolección de resultados tendría lugar antes decommit()
en la transacción Como sigue:
Código Bloque 3
$db->beginTransaction();
try{
$stmt1 = $db->prepare(...);
$stmt1->execute();
$stmt2 = $db->prepare(...);
$stmt2->execute();
$stmt3 = $db->prepare(...);
$stmt3->execute();
$result = $stmt3->fetchAll();
if($result[0]['val'] == something){
$stmt4 = $db->prepare(...);
$stmt4->execute();
}else{
$db->rollBack();
return false;
}
$db->commit();
return true;
}catch(Exception $e){
$db->rollBack();
throw $e;
return false;
}
esto funcionara? Específicamente, ¿puedo incluir el$result = $stmt3->fetchAll();
antes de elcommit()
y luego ejecuta la consulta condicional?
Además, no estoy completamente seguro de esto, pero ¿requiero el$db->rollBack();
dentro detry
bloque, si se sale del código (return false
) antes decommit()
?