¿Los INSERTs se comprometen automáticamente?

13

Nuestra aplicación dispara una consulta INSERT a la base de datos MySQL para agregar registros. Quiero saber si los registros se auto-confirman o no. Si ejecuto el comando ROLLBACK, ¿cuándo realiza la reversión la base de datos? ¿Es posible un ROLLBACK después de un COMMIT?

RPK
fuente
Solo para aclarar, etiqueté como 'innodb' hace 19 horas, ya que InnoDB usa COMMIT / ROLLBACK.
RolandoMySQLDBA
Esto obtiene un +1 para recordar a los desarrolladores y DBA que presten atención al comportamiento transaccional, los paradigmas de aplicaciones correspondientes que respaldan las transacciones y sus consecuencias (buenas o malas).
RolandoMySQLDBA
Respondí tu pregunta con un comentario debajo de mi respuesta.
RolandoMySQLDBA

Respuestas:

10

La respuesta a su pregunta depende de si está o no dentro de una transacción que abarcará más de un estado de cuenta. (Ha etiquetado la pregunta con InnoDB, la respuesta sería diferente con MyISAM).

Del manual de referencia: http://dev.mysql.com/doc/refman/5.1/en/commit.html

Por defecto, MySQL se ejecuta con el modo de confirmación automática habilitado. Esto significa que tan pronto como ejecuta una instrucción que actualiza (modifica) una tabla, MySQL almacena la actualización en el disco para que sea permanente.

Entonces, sí, de manera predeterminada, si solo está usando INSERT, los registros que inserte se confirmarán, y no tiene sentido intentar revertirlos. (Esto es efectivamente lo mismo que envolver cada declaración entre BEGINy COMMIT.)

Sin embargo, si se trata de transacciones explícitamente, tendrá que usar COMMITpara confirmar almacenar los registros, pero también podrá usar ROLLBACK.

Puede iniciar una transacción explícitamente usando START TRANSACTION(o BEGIN). Esto es independiente de la autocommitconfiguración (activada de forma predeterminada):

Con START TRANSACTION, la confirmación automática permanece deshabilitada hasta que finalice la transacción con COMMIT o ROLLBACK. El modo de confirmación automática vuelve a su estado anterior.

Alternativamente, si autocommit=0, creo que cualquier declaración después de otro final de la transacción, comenzará una transacción (pero aún puede usarla START TRANSACTIONexplícitamente); esa es al menos la forma en que interpreto esto :

El modo de confirmación automática. Si se establece en 1, todos los cambios en una tabla surten efecto inmediatamente. Si se establece en 0, debe usar COMMIT para aceptar una transacción o ROLLBACK para cancelarla. Si la confirmación automática es 0 y la cambia a 1, MySQL realiza un COMPROMISO automático de cualquier transacción abierta. Otra forma de comenzar una transacción es usar una instrucción START TRANSACTION o BEGIN. Consulte la Sección 12.3.1, “INICIAR TRANSACCIÓN, COMPROMISO y Sintaxis ROLLBACK”

Más específicamente, "otra forma de comenzar una transacción" parece implicar que establecer "autocommit = 0" es suficiente para iniciar una transacción (al menos justo antes de cada declaración al inicio de una sesión o que sigue a COMMIT/ ROLLBACK). Sugeriría usar de manera explícita BEGINo de START TRANSACTIONtodos modos, incluso si es así autocommit=0, ya que puede ser más claro ver cuándo comienza o termina la transacción.

(La forma en que inicia una transacción puede depender de la forma en que su aplicación usa MySQL).

Bruno
fuente
1
Merece un +1 para definir completamente los protocolos transaccionales.
RolandoMySQLDBA
@Bruno, para MyISAM donde "commit" y "rollback" no funcionan, ¿los insertos no estarían comprometidos a medias?
Pacerier
7

Por defecto, InnoDB está configurado para autocommitir = 1 u ON . Una vez cometidos, no se pueden revertir .

Tendría que hacer una de dos cosas para deshabilitarlo en el futuro:

OPCIÓN 1: Agregue esto a /etc/my.cnf y reinicie mysql

[mysqld]
autocommit=0

OPCIÓN 2: Realice uno de estos en la conexión de base de datos abierta antes de comenzar cualquier SQL significativo

SET autocommit = 0;
START TRANSACTION;

Bajo estas dos opciones, tendría que realizar un COMMIT manual o un ROLLBACK manual .

CONSIDERACIÓN

Si la tabla es MyISAM, entonces la explicación es más simple. Como no hay transacciones para el motor de almacenamiento MyISAM, todos los INSERT, UPDATE y DELETE ejecutados son permanentes. No hay retrocesos en absoluto.

RolandoMySQLDBA
fuente
Para aclaraciones adicionales, mi respuesta se dirige a los motores de almacenamiento InnoDB y MyISAM.
RolandoMySQLDBA
1
En caso de que la confirmación automática esté desactivada en InnoDB y mi aplicación esté activando Insertar consultas, y me olvide de ejecutar la confirmación, ¿qué tan pronto se pierden los cambios?
RPK
Si su aplicación activa manualmente un COMMIT después de cada INSERT, se escribe y no se puede eliminar. Si la conexión de base de datos muere antes de COMPROMETERSE, todos los cambios se pierden y se produce la reversión. Si realiza cualquier DDL (CREATE TABLE, DROP TABLE, ALTER TABLE, etc.) o emite manualmente un bloqueo de tabla, los INSERT se comprometen automáticamente. Si usa START TRANSACTION, se confirman todos los cambios no confirmados.
RolandoMySQLDBA
1
Con respecto a "Si usa INICIAR TRANSACCIÓN, se confirman todos los cambios no confirmados". (en el contexto de los DDL, de lo contrario se revierte), también hay una confirmación implícita antes (la confirmación implícita después es de la versión 5.5.3 de acuerdo con la documentación).
Bruno
1
"Si usa START TRANSACTION, se confirman todos los cambios no confirmados". - Obtuve esa idea de la Guía de estudio de certificación de MySQL 5.0 (ISBN 0-672-32812-7) Página 418 que nombra INICIAR TRANSACCIÓN, CONFIGURAR AUTOCOMMIT = 1, BLOQUEAR TABLAS, DESBLOQUEAR TABLAS, TRUNCATE TABLE, RENAME TABLE, DROP INDEX, DROP TABLE , DROP DATABASE, CREATE INDEX, BEGIN y ALTER TABLE bajo los encabezados "En algunas circunstancias, la transacción actual puede finalizar implícitamente: Si emite cualquiera de las siguientes declaraciones, InnoDB confirma implícitamente las declaraciones no confirmadas anteriores de la transacción actual y comienza un nueva transacción ".
RolandoMySQLDBA