Te doy la bienvenida a nuestro espacio, ahora vas a hallar la resolución a lo que andabas buscando.
Solución:
Actualización noviembre 2020: @Dharman dio una mejor respuesta con más detalles sobre las transacciones en mysqli, solo verifíquelo en su lugar: https://stackoverflow.com/a/63764001/569101
Bueno, de acuerdo con el documento php, tienes razón.
query("CREATE TABLE Language LIKE CountryLanguage");
/* set autocommit to off */
$mysqli->autocommit(FALSE);
/* Insert some values */
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Bavarian', 'F', 11.2)");
$mysqli->query("INSERT INTO Language VALUES ('DEU', 'Swabian', 'F', 9.4)");
/* commit transaction */
$mysqli->commit();
/* drop table */
$mysqli->query("DROP TABLE Language");
/* close connection */
$mysqli->close();
?>
En el ejemplo anterior:
- los
CREATE TABLE
se compromete automáticamente porque es el comportamiento predeterminado. - los
INSERT INTO
no son auto cometido debido a laautocommit(FALSE)
. - los
DROP TABLE
se compromete automáticamente porque elautocommit(FALSE)
era Reiniciar por el->commit();
.
j0k es principalmente correcto, excepto en la tabla desplegable.
La confirmación automática no está activada con el ->commit()
En cambio, DROP TABLE es una consulta DDL, y las consultas DDL siempre se confirman implícitamente y confirmarán todo el trabajo no confirmado anteriormente.
Entonces, si no comprometió el trabajo, la consulta DDL forzaría este compromiso.
¿Cómo usar transacciones en mysqli?
Requisito previo
Para que las transacciones se comporten correctamente, debe habilitar el informe de errores de excepción. De lo contrario, mysqli no informará errores y la transacción no se realizará correctamente. Alternativamente, puede verificar manualmente cada consulta, pero eso no se recomienda. Para conectarse correctamente con mysqli, use las siguientes 3 líneas:
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');
$mysqli->set_charset('utf8mb4'); // always set the charset
Actas
Hay dos formas posibles de crear una transacción usando mysqli. De forma predeterminada, todas las consultas/declaraciones se confirman tan pronto como se realizan. Puede desactivar la confirmación automática o utilizar una transacción de una sola vez.
Las transacciones se comprometen a la base de datos en las siguientes situaciones:
- al llamar
commit
- después de configurar autocommit=1
- al iniciar otra transacción
- al realizar la consulta DDL
- y en algunas otras situaciones. Para obtener más información, consulte Declaraciones que provocan una confirmación implícita.
Usando la confirmación automática (false)
Si desactiva la confirmación automática, usted decide cuándo desea confirmar, pero llamando commit()
no vuelve a activar la confirmación automática.
//Start transaction
$mysqli->autocommit(false);
$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');
$directorId = $mysqli->insert_id;
$movieTitle = 'Jurassic Park';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();
$mysqli->commit();
// Changes are committed, but autocommit is not switched back on
// Following queries are still transactional. They will not be committed unless you call commit or switch autocommit back on
$mysqli->query('INSERT INTO director(name) VALUE("James Cameron")');
$directorId = $mysqli->insert_id;
$movieTitle = 'Titanic';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();
$mysqli->autocommit(true);
// All queries are committed and everything that follows will be immediately committed.
Usando begin_transaction()
Puede iniciar una transacción de una sola vez usando begin_transaction()
. esto no se pone autocommit=false
así que cuando llames commit()
finaliza la transacción sin iniciar una nueva.
//Start transaction
$mysqli->begin_transaction();
$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');
$directorId = $mysqli->insert_id;
$movieTitle = 'Jurassic Park';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();
$mysqli->commit();
// Changes are committed and the transaction has ended
// Following queries will be committed one by one as soon as they are peformed.
$mysqli->query('INSERT INTO director(name) VALUE("James Cameron")');
$directorId = $mysqli->insert_id;
$movieTitle = 'Titanic';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();
Ejecución de sentencias DDL
Algunas sentencias SQL activan una confirmación explícita pero no afectan el valor de autocommit
.
//Start transaction
$mysqli->autocommit(false);
$mysqli->query('INSERT INTO director(name) VALUE("Steven Spielberg")');
$directorId = $mysqli->insert_id;
$movieTitle = 'Jurassic Park';
$stmt = $mysqli->prepare('INSERT INTO movie(title, directorId) VALUE(?,?)');
$stmt->bind_param('ss', $movieTitle, $directorId);
$stmt->execute();
// The following will call commit but it will not set autocommit=true
$mysqli->query('TRUNCATE TABLE movie_genre');
// if you want to switch autocommit back on, you have to call:
$mysqli->autocommit(true);
Retroceder
Si ocurre una excepción, PHP finalizará la ejecución del script y el código nunca llegará al commit
declaración. Sin embargo, en algunas situaciones, es posible que desee revertir la transacción explícitamente, por ejemplo, para evitar llamar a commit accidentalmente en otro lugar del código.
Aquí hay un ejemplo de cómo sería una transacción de este tipo. La segunda consulta intenta insertarse en una tabla inexistente, lo que significa que mysqli generará una excepción. En lugar de dejar que el script PHP muera, detectamos la excepción y revertimos la transacción. El valor 4
nunca se insertará en la base de datos porque ambas consultas se revirtieron.
try
// Start transaction
$mysqli->begin_transaction();
$mysqli->query('INSERT INTO some_table(col2) VALUE(4)');
$mysqli->query('INSERT INTO does_not_exist(col2) VALUE(4)');
// Commit changes
$mysqli->commit();
catch (Throwable $e)
// Something went wrong. Rollback
$mysqli->rollback();
// Rethrow the exception so that PHP does not continue with the execution and the error can be logged in the error_log
throw $e;
Nos encantaría que puedieras compartir este tutorial si lograste el éxito.