¿Por qué se deben deshacer las transacciones no confirmadas en orden inverso?

19

Tengo un registro de base de datos donde algunas transacciones ganan (se confirman antes del bloqueo) y otras pierden (aún no se han comprometido). Aprendimos en clase que las acciones de los perdedores deben deshacerse al revés.

¿Hay alguna razón para hacer esto al revés? ¿Alguien puede dar un ejemplo simple de un registro donde deshacer deshacer daría resultados incorrectos?

prjctdth
fuente
¿No debería hacerse esta pregunta en otro sitio web más específico?
nbro

Respuestas:

35

Transacciones originales:

  1. Insertar registro .r
  2. Actualice algún campo de r .Fr

Deshacer hacia adelante:

  1. Eliminar registro .r
  2. Invierta la actualización a : ¡espera, r ya no existe! Esto causa un error.rr
DylanSp
fuente
¿Las cosas deben deshacerse individualmente físicamente en orden inverso si el sistema puede determinar en qué estado deben revertirse las cosas y puede aplicar todos los cambios necesarios antes de procesar cualquier otra cosa?
supercat
11
Deshacer cambios en orden inverso lo hace fácil. ¿Por qué tratarías de hacerlo difícil para ti?
gnasher729
1
No, el sistema no lo hará todo, pero aún lo resolverá en orden inverso.
Mal
3
En muchos sistemas de bases de datos del mundo real, no sería posible hacerlo en orden inverso debido a restricciones clave en las tablas.
SeanR
11

Para agregar a la respuesta de DylanSp, el intento de actualizar un campo en un registro no existente fallará, pero el resultado seguirá siendo el resultado esperado: el registro r no existe.

Sin embargo, considere una situación en la que la eliminación de un registro realmente fallará:

  1. Insertar orden O.
  2. Insertar línea de pedido L.

Asumamos, no de manera poco realista, que cada OrderLine debe estar relacionada con un Order.

Ahora, revertir la transacción que comienza con la eliminación del Pedido fallará porque eso violaría nuestra regla comercial.

Así que después

  1. Eliminar orden O. (FALLO)
  2. Eliminar Ordeline L. (ÉXITO)

Podemos terminar con un pedido existente (sin una línea de pedido).

Por supuesto, en este caso podríamos usar una eliminación en cascada, pero eso significaría que el paso 2 fallaría (sin impacto). Peor aún, puede ser un comportamiento no deseado implementar eliminaciones en cascada en los pedidos.

Oerkelens
fuente
Vale, esto tiene sentido. Gracias por su ayuda
prjctdth
¿Es correcto suponer que no se violaron las restricciones antes o después de la transacción en circunstancias "normales"? Por normal, quiero decir que la transacción no habría fallado si solo una persona estuviera usando la base de datos. Si esto es cierto, ¿por qué sería importante no introducir violaciones de restricciones durante el proceso de deshacer? Parece que las restricciones se pueden desactivar al comienzo de deshacer y habilitarse una vez que se completa la operación.
Noctis Skytower
2
@NoctisSkytower Desactivar las restricciones durante una operación normal de E / S las vuelve inútiles. Existen por una razón. Mi ejemplo ilustra claramente cómo se pueden cumplir las restricciones en circunstancias normales, pero violadas durante la reversión. Desactivar las restricciones durante la reversión complica innecesariamente las cosas y soluciona el problema incorrecto. El problema no es la restricción, el problema es la violación al tratar de retroceder incorrectamente.
oerkelens
Sí, eso tiene sentido, pero ¿por qué verificar las restricciones durante la reversión? Suponiendo que los retrocesos están diseñados para garantizar que se completen sin problemas, ¿por qué perder innecesariamente el tiempo para verificar las restricciones si se sabe que no serán violadas para cuando se complete el retroceso? Por cierto, eso debería ser una garantía porque si falla una reversión, la base de datos aparentemente necesitaría avanzar, lo que no puede hacer.
Noctis Skytower
1
@NoctisSkytower debería ser imposible para el DB estar en un estado donde se violen las restricciones, incluso si es un estado temporal. Si toda la reversión es atómica, entonces no importa en qué orden suceda porque no hay orden, es una sola instrucción que "sucede de una vez". Si hay dos o más transacciones que se deshacen por separado en algún orden, entonces es obligatorio que el orden sea tal que cualquier observador que lea los datos en el medio solo pueda ver una situación en la que se cumplan todas las restricciones.
Peteris
6

Vamos por analogía: digamos que vas a cenar.

  1. Ponte calcetines.
  2. Ponte los zapatos.
  3. Levántate.
  4. Camina a la puerta.

Entonces recibes una llamada telefónica. Planes de cena cancelados.

  1. Quítate los calcetines.
  2. Quítate los zapatos.
  3. Siéntate.
  4. Aléjate de la puerta.

Algo sale mal allí. Puede tropezar y lastimarse. O, más probablemente, se dará cuenta de que algunas acciones no se pueden deshacer hasta que las acciones posteriores se deshagan primero.

Deshacer lo último que estaba haciendo lo lleva de regreso a donde estaba cuando ocurrió el penúltimo paso. Luego deshaces ese paso y repites, retrocediendo hasta que no quede nada. Por otro lado, revertir el primer paso puede no ser posible dados los estados que siguen a los pasos posteriores.

matemáticamente hablando: las acciones pueden no conmutar, por lo que siempre que importa qué paso hagas primero o segundo, el orden en que deshagas los pasos será importante.

Joel
fuente
3

Esto es correcto porque las transacciones se construyen una encima de la otra y el resultado de una transacción depende en gran medida de la situación anterior a su confirmación.

Veamos las transacciones financieras:

(al principio, antes de las transacciones ame debe 100 USD)

  1. a me debe 100 USD (ahora deuda total 200)
  2. arecibe un 10% de descuento en lo que me debe. (ahora deuda total 180)

Digamos que quiero cancelar las dos transacciones.

Si cancelamos el primero primero, terminaremos con:

  1. menor deuda 100 (ahora tiene deuda 80)
  2. cancelar 10% de descuento (ahora tiene deuda 80 / 0.9 = 88)

Esto está mal, necesitamos volver a la deuda de 100. Eso será correcto si cancelamos las transacciones en orden inverso.

  1. cancelar descuento - ahora la deuda es 200
  2. menor deuda 100 - ahora la deuda es 100
thebeancounter
fuente
2

Suponga que hay una tabla T con una sola columna.

Suponga que el "registro de deshacer" es un archivo de base de datos que contiene transacciones no confirmadas, y que el "registro de deshacer" es un archivo de base de datos que contiene transacciones confirmadas y no confirmadas que aún no se han aplicado a los archivos de datos.

At 8:00 A.M., Transaction 100 inserts rows with values 101, 102 and 103 into table T. At 8:10 A.M., Transaction 100 is committed and the commit for transaction 100 completes. At 8:15 A.M., Transaction 200 updates row 101 to 201, 102 to 202 and 103 to 203. At 8:20 A.M., Transaction 200 has not been committed and remains in the undo log of the database. At 8:25 A.M., Transaction 300 increments each row by 50, changing row 201 to 251, 202 to 252, and 203 to 253. At 8:30 A.M., Transaction 300 has not been committed and remains in the undo log of the database. At 8:35 A.M., The instance providing access to the database crashes.

At 8:40 A.M., The instance is restarted, and the database files are opened as the instance is started:

              The committed values in T are still 101, 102 and 103.

              Since 201, 202, and 203, and 251, 252 and 253
              are not committed, if they are written into the "redo
              log" of the database, there is a need to "roll back"
              the transactions AFTER the "redo log" is applied.

              Since 201, 202, and 203, and 251, 252 and 253
              are not committed, they are in the "undo log"
              of the database.

              The undo log of the database is used BOTH to (1) roll
              back a transaction that is deliberately rolled 
              back in the memory structure of the database instance, 
              and also (2) during the instance recovery at 8:40 A.M.

At 8:41 A.M., The redo log has been applied, and the T table contains values 251, 252 and 253 in the instance memory.

              The undo log has not yet been applied.

At 8:42 A.M., The undo log is applied in the reverse order: Uncommitted transaction 300 is undone, and Uncommitted transaction 200 is undone.

¿Por qué AMBAS transacciones confirmadas y no confirmadas escritas en el archivo de registro de rehacer? La razón de esto es proporcionar una recuperación en un punto en el tiempo.

Esto significa que el contenido del archivo "redo log" NO es consistente con la transacción. Por este motivo, siempre que el registro de rehacer se use para aplicar transacciones confirmadas a los archivos de datos, el "registro de deshacer" DEBE TAMBIÉN usarse para revertir transacciones no confirmadas.

¿Por qué las transacciones en el "registro de deshacer" se revierten en el orden inverso? La transacción 300 ha agregado 50 al valor existente de cada columna de cada fila. Por lo tanto, si la transacción 200 se revierte primero, los valores cambiarán de 251, 252 y 253 a 201, 202 y 203. Si la transacción 300 se revierte en último lugar, los valores serían 151, 152 y 153, que no coinciden Los valores comprometidos originales.

Referencias

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1670195800346464273

AB
fuente
0

No es inherentemente cierto. La reversión puede simplemente volver a aplicar los bloques que se almacenaron en caché en el registro de deshacer para que el estado final sea el mismo que el estado inicial. Como el registro se escribió en orden de reenvío, hice que mi reversión también se aplicara en orden de reenvío. El orden no importó en absoluto porque la reversión volvería a intentar hasta que el archivo de registro se marcara como resuelto.

Joshua
fuente