En informática , ACID ( atomicidad , consistencia , aislamiento , durabilidad ) es un conjunto de propiedades de las transacciones de bases de datos destinadas a garantizar la validez de los datos a pesar de errores, cortes de energía y otros contratiempos. En el contexto de las bases de datos , una secuencia de operaciones de base de datos que satisface las propiedades ACID (que pueden percibirse como una única operación lógica sobre los datos) se denomina transacción . Por ejemplo, una transferencia de fondos de una cuenta bancaria a otra, incluso si implica múltiples cambios como debitar una cuenta y acreditar otra, es una única transacción.
En 1983, [1] Andreas Reuter y Theo Härder acuñaron el acrónimo ACID , basándose en trabajos anteriores de Jim Gray [2] que nombró atomicidad, consistencia y durabilidad, pero no aislamiento, al caracterizar el concepto de transacción. Estas cuatro propiedades son las principales garantías del paradigma de transacción, que ha influido en muchos aspectos del desarrollo de los sistemas de bases de datos .
Según Gray y Reuter, el sistema de gestión de información de IBM admitía transacciones ACID ya en 1973 (aunque el acrónimo se creó más tarde). [3]
Las características de estas cuatro propiedades según las definen Reuter y Härder son las siguientes:
Las transacciones suelen estar compuestas de múltiples instrucciones . La atomicidad garantiza que cada transacción se trate como una única "unidad", que puede tener éxito o fallar por completo: si alguna de las instrucciones que constituyen una transacción no se completa, la transacción completa falla y la base de datos permanece sin cambios. Un sistema atómico debe garantizar la atomicidad en todas y cada una de las situaciones, incluidas las fallas de energía, los errores y las caídas. [4] Una garantía de atomicidad evita que las actualizaciones de la base de datos se realicen solo parcialmente, lo que puede causar mayores problemas que rechazar toda la serie de inmediato. Como consecuencia, otro cliente de la base de datos no puede observar que la transacción está en progreso. En un momento dado, aún no ha sucedido y, en el siguiente, ya ha sucedido en su totalidad (o no sucedió nada si la transacción se canceló en progreso).
La consistencia garantiza que una transacción solo pueda llevar la base de datos de un estado consistente a otro, preservando las invariantes de la base de datos : cualquier dato escrito en la base de datos debe ser válido de acuerdo con todas las reglas definidas, incluidas las restricciones , las cascadas , los disparadores y cualquier combinación de las mismas. Esto evita la corrupción de la base de datos por una transacción ilegal. Un ejemplo de una invariante de la base de datos es la integridad referencial , que garantiza la relación clave primaria - clave externa . [5]
Las transacciones se ejecutan a menudo de forma concurrente (por ejemplo, varias transacciones que leen y escriben en una tabla al mismo tiempo). El aislamiento garantiza que la ejecución concurrente de transacciones deje la base de datos en el mismo estado que se habría obtenido si las transacciones se hubieran ejecutado secuencialmente. El aislamiento es el objetivo principal del control de concurrencia ; dependiendo del nivel de aislamiento utilizado, los efectos de una transacción incompleta podrían no ser visibles para otras transacciones. [6]
La durabilidad garantiza que una vez que se ha confirmado una transacción, permanecerá confirmada incluso en caso de una falla del sistema (por ejemplo, un corte de energía o una caída ). Esto generalmente significa que las transacciones completadas (o sus efectos) se registran en una memoria no volátil . [7]
Los siguientes ejemplos ilustran con más detalle las propiedades ACID. En estos ejemplos, la tabla de la base de datos tiene dos columnas, A y B. Una restricción de integridad exige que el valor de A y el valor de B sumen 100. El siguiente código SQL crea una tabla como la descrita anteriormente:
CREAR TABLA acidtest ( A ENTERO , B ENTERO , VERIFICAR ( A + B = 100 ));
La atomicidad es la garantía de que una serie de operaciones de base de datos en una transacción atómica se realizarán todas (operación exitosa) o no se realizará ninguna (operación fallida). La serie de operaciones no se puede separar y ejecutar solo algunas de ellas, lo que hace que la serie de operaciones sea "indivisible". Una garantía de atomicidad evita que las actualizaciones de la base de datos se realicen solo parcialmente, lo que puede causar mayores problemas que rechazar la serie completa por completo. En otras palabras, atomicidad significa indivisibilidad e irreducibilidad. [8] Alternativamente, podemos decir que una transacción lógica puede estar compuesta de varias transacciones físicas. A menos que y hasta que se ejecuten todas las transacciones físicas que la componen, la transacción lógica no se habrá realizado.
Un ejemplo de una transacción atómica es una transferencia monetaria de la cuenta bancaria A a la cuenta B. Consiste en dos operaciones, retirar el dinero de la cuenta A y depositarlo en la cuenta B. No querríamos ver la cantidad retirada de la cuenta A antes de estar seguros de que también ha sido transferida a la cuenta B. Realizar estas operaciones en una transacción atómica garantiza que la base de datos permanezca en un estado consistente , es decir, el dinero no se debita ni se acredita si alguna de esas dos operaciones falla. [9]
La coherencia es un término muy general que exige que los datos cumplan con todas las reglas de validación. En el ejemplo anterior, la validación es un requisito de que A + B = 100. Se deben comprobar todas las reglas de validación para garantizar la coherencia. Supongamos que una transacción intenta restar 10 de A sin alterar B. Como la coherencia se comprueba después de cada transacción, se sabe que A + B = 100 antes de que comience la transacción. Si la transacción elimina 10 de A con éxito, se logrará la atomicidad. Sin embargo, una comprobación de validación mostrará que A + B = 90 , lo que es incompatible con las reglas de la base de datos. Se debe cancelar toda la transacción y las filas afectadas deben revertirse a su estado anterior a la transacción. Si hubiera habido otras restricciones, activadores o cascadas, cada operación de cambio individual se habría comprobado de la misma manera que antes antes de que se confirmara la transacción. Pueden surgir problemas similares con otras restricciones. Es posible que hayamos requerido que los tipos de datos de A y B fueran números enteros. Si, por ejemplo, ingresáramos el valor 13,5 para A , la transacción se cancelaría o el sistema podría generar una alerta en forma de un disparador (si/cuando el disparador se haya escrito a tal efecto). Otro ejemplo serían las restricciones de integridad, que no nos permitirían eliminar una fila en una tabla cuya clave principal esté referenciada por al menos una clave externa en otras tablas.
Para demostrar el aislamiento, suponemos que dos transacciones se ejecutan al mismo tiempo y que cada una intenta modificar los mismos datos. Una de las dos debe esperar hasta que la otra finalice para mantener el aislamiento.
Consideremos dos transacciones:
En conjunto, hay cuatro acciones:
Si estas operaciones se realizan en orden, se mantiene el aislamiento, aunque T 2 debe esperar. Considere lo que sucede si T 1 falla a mitad de camino. La base de datos elimina los efectos de T 1 y T 2 solo ve datos válidos.
Al intercalar las transacciones, el orden real de las acciones podría ser:
Nuevamente, considere lo que sucede si T 1 falla mientras modifica B en el Paso 4. Para cuando T 1 falla, T 2 ya ha modificado A; no se puede restaurar al valor que tenía antes de T 1 sin dejar una base de datos inválida. Esto se conoce como una contención de escritura-escritura , [10] porque dos transacciones intentaron escribir en el mismo campo de datos. En un sistema típico, el problema se resolvería volviendo al último estado bueno conocido, cancelando la transacción fallida T 1 y reiniciando la transacción interrumpida T 2 desde el estado bueno.
Considere una transacción que transfiere 10 de A a B. Primero, quita 10 de A, luego agrega 10 a B. En este punto, se le informa al usuario que la transacción fue exitosa. Sin embargo, los cambios aún están en cola en el búfer del disco a la espera de ser confirmados en el disco. Se corta la energía y los cambios se pierden, pero el usuario asume (comprensiblemente) que los cambios persisten.
El procesamiento de una transacción a menudo requiere una secuencia de operaciones que está sujeta a fallas por varias razones. Por ejemplo, es posible que el sistema no tenga espacio libre en sus unidades de disco o que haya agotado el tiempo de CPU asignado. Existen dos familias populares de técnicas: el registro de escritura anticipada y la paginación de sombra . En ambos casos, se deben adquirir bloqueos en toda la información que se va a actualizar y, según el nivel de aislamiento, posiblemente también en todos los datos que se puedan leer. En el registro de escritura anticipada, se garantiza la durabilidad escribiendo el cambio prospectivo en un registro persistente antes de cambiar la base de datos. Eso permite que la base de datos vuelva a un estado consistente en caso de una falla. En el seguimiento, las actualizaciones se aplican a una copia parcial de la base de datos y la nueva copia se activa cuando se confirma la transacción.
Muchas bases de datos dependen del bloqueo para proporcionar capacidades ACID. El bloqueo significa que la transacción marca los datos a los que accede para que el DBMS sepa que no debe permitir que otras transacciones los modifiquen hasta que la primera transacción tenga éxito o falle. El bloqueo siempre debe adquirirse antes de procesar los datos, incluidos los datos que se leen pero no se modifican. Las transacciones no triviales suelen requerir una gran cantidad de bloqueos, lo que genera una sobrecarga sustancial y bloquea otras transacciones. Por ejemplo, si el usuario A está ejecutando una transacción que tiene que leer una fila de datos que el usuario B desea modificar, el usuario B debe esperar hasta que se complete la transacción del usuario A. El bloqueo de dos fases se aplica a menudo para garantizar un aislamiento completo.
Una alternativa al bloqueo es el control de concurrencia multiversión , en el que la base de datos proporciona a cada transacción de lectura la versión anterior, sin modificar, de los datos que está siendo modificada por otra transacción activa. Esto permite que los lectores operen sin adquirir bloqueos, es decir, las transacciones de escritura no bloquean las transacciones de lectura y los lectores no bloquean a los escritores. Volviendo al ejemplo, cuando la transacción del usuario A solicita datos que el usuario B está modificando, la base de datos proporciona a A la versión de esos datos que existía cuando el usuario B inició su transacción. El usuario A obtiene una vista consistente de la base de datos incluso si otros usuarios están cambiando los datos. Una implementación, denominada aislamiento de instantáneas , relaja la propiedad de aislamiento.
Garantizar las propiedades ACID en una transacción distribuida en una base de datos distribuida , donde ningún nodo es responsable de todos los datos que afectan a una transacción, presenta complicaciones adicionales. Las conexiones de red pueden fallar, o un nodo puede completar con éxito su parte de la transacción y luego ser requerido para revertir sus cambios debido a una falla en otro nodo. El protocolo de confirmación de dos fases (que no debe confundirse con el bloqueo de dos fases ) proporciona atomicidad para las transacciones distribuidas para garantizar que cada participante en la transacción esté de acuerdo sobre si la transacción debe confirmarse o no. [11] Brevemente, en la primera fase, un nodo (el coordinador) interroga a los otros nodos (los participantes), y solo cuando todos responden que están preparados, el coordinador, en la segunda fase, formaliza la transacción.
Operación durante la cual un procesador puede leer una ubicación y escribirla simultáneamente en la misma operación de bus. Esto evita que cualquier otro procesador o dispositivo de E/S escriba o lea la memoria hasta que se complete la operación.