Saltar al contenido

¿Cómo iniciar y finalizar la transacción en mysqli?

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 INTOno son auto cometido debido a la autocommit(FALSE).
  • los DROP TABLE se compromete automáticamente porque el autocommit(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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *