database transactions persistence unit-of-work

database - ¿Se necesita algún tipo de comportamiento transaccional fuera de las bases de datos?



transactions persistence (7)

Las confirmaciones de Subversion son transaccionales: son verdaderamente atómicas, por lo que una confirmación interrumpida no deja el repositorio en un estado incoherente.

No me atrevería a hacer nada complejo en una base de datos sin transacciones. Casi siempre hay un comando incorporado fácil de usar. Pero cuando comienzas a trabajar con otros datos persistentes simplemente no obtienes este soporte de transacción simple de usar. Algunos ejemplos son

  • sistemas de archivos
  • servicios web (ninguno que he usado)

Incluso en datos no persistentes, a menudo es útil deshacer un bloque de trabajo, siguiendo una excepción. Ninguna de las estructuras de datos estándar que obtiene con un idioma admite transacciones.

Lo que me gustaría saber es, ¿por qué son las bases de datos el caso especial?

¿Existen enlaces útiles al tema del comportamiento transaccional fuera de las bases de datos?


Los sistemas de archivos modernos tienen transacciones. Simplemente son transparentes para el usuario final.

NTFS, XFS, JFS, EXT3 y ReiserFS todos, solo por nombrar algunos.

Y eso es solo interno al sistema de archivos. Muchos sistemas operativos también admiten el bloqueo de archivos (consulte flock (2) en el mundo * NIX, por ejemplo) con bloqueos exclusivos (escritura) y compartidos (lectura).

Editar: si lo piensas bien, los sistemas de archivos no tienen niveles de aislamiento como los DB modernos porque una vez que terminas de leer un archivo, tradicionalmente lo cierras si no lo bloqueaste. Luego lo vuelves a abrir cuando quieras escribir en él.


Los sistemas de mensajería son otro ejemplo de administradores de recursos transaccionales.

Es decir, puede asegurarse de que un consumidor de mensajes procese con éxito un mensaje de la cola. Si el proceso falla, entonces el mensaje queda en la cola.

Además, un sistema de mensajería puede participar en una transacción distribuida con otro administrador de recursos.

Más información en


Clojure usa Software Transactional Memory , que usa transacciones para que sea más fácil y seguro escribir programas de subprocesos múltiples sin bloqueos manuales. Clojure tiene estructuras de datos inmutables con referencias mutables para ellos, y se requieren transacciones para cambiar las referencias.


Debo discrepar respetuosamente: los sistemas transaccionales no son automática y exclusivamente motores de bases de datos, sino todo lo contrario ...

Implementé un mecanismo de transacción de aplicación (en .NET) que es distinto de una transacción de base de datos. En realidad, es bastante fácil (unas pocas horas de trabajo, incluido un conjunto de pruebas de unidades). Está escrito completamente en C # sin dependencias de ninguna funcionalidad de base de datos ni de ningún otro componente. Pero primero un poco de contexto ...

Esta característica que no es de transacción de base de datos existe en varias manifestaciones en la plataforma Java, como EJB, ESB, JMS y, a menudo, en asociación con BPM. Algunas de estas manifestaciones usan una base de datos subyacente, pero no siempre y no por necesidad. Otras plataformas tienen manifestaciones similares, como MSMQ.

La mayoría de los sistemas de control de versiones heredadas NO implementan la semántica de transacciones ACID. Como dijo ddaa, CVS no lo hace, pero Subversion (su sucesor) sí. Visual Source Safe no. Si investigas Subversion, puedes encontrar tablas de comparación que lo destacan.

Ahora, para el punto crítico, una transacción de base de datos o su equivalente no garantiza una lógica comercial segura. Aunque amo Subversion, irónicamente es un gran ejemplo de este hecho.

Puede usar Subversion de forma religiosa, junto con un script de compilación automatizado (un comando que compila, prueba y empaqueta su aplicación) y aún así compromete una compilación no realizada en el repositorio de control de origen. Lo he visto repetidamente Por supuesto, es incluso más fácil con herramientas de control de fuente no basadas en ACID como VSS. Pero es impactante para muchas personas saber que es posible con herramientas como Subversion.

Permítanme por favor diseñar el escenario. Usted y un compañero de trabajo están desarrollando una aplicación y están utilizando Subversion para el repositorio de control de origen. Ambos están codificando y comprometiéndose ocasionalmente con el repositorio. Realiza algunos cambios, ejecuta una compilación limpia (recompila todos los archivos fuente) y todas las pruebas pasan. Entonces, comprometes tus cambios y te vas a casa. Su compañero de trabajo ha estado trabajando en sus propios cambios, por lo que también ejecuta una compilación limpia, ve pasar todas las pruebas y se compromete con el repositorio. Pero, su compañero de trabajo luego actualiza desde el repositorio, hace algunos cambios más, ejecuta una construcción limpia, ¡y la compilación explota en su rostro! Revierte sus cambios, las actualizaciones del repositorio nuevamente (solo para estar seguro), y descubre que una compilación limpia todavía explota. Su compañero de trabajo pasa las próximas horas solucionando problemas en la construcción y la fuente, y eventualmente encuentra un cambio que realizó antes de que usted se fuera y eso está causando la falla en la construcción. Lanza un desagradable correo electrónico a usted y a su jefe mutuo, quejándose de que rompió la construcción y luego se fue a su casa descuidadamente. Llegas por la mañana para encontrar a tu compañero de trabajo y a tu jefe esperando en tu escritorio para maldecirte, ¡y todos los demás están mirando! Entonces ejecutas rápidamente una compilación limpia y les muestras que la compilación no está rota (todas las pruebas pasan, como anoche).

¿Como es esto posible? Es posible porque la estación de trabajo de cada desarrollador no es parte de la transacción ACID; Subversion solo garantiza los contenidos del repositorio. Cuando su compañero de trabajo se actualizó desde el repositorio, su estación de trabajo contenía una copia mixta de los contenidos del repositorio (incluidos sus cambios) y sus propios cambios no confirmados. Cuando su compañero de trabajo ejecutó una compilación limpia en su estación de trabajo, estaba invocando una transacción comercial que NO estaba protegida por la semántica de ACID. Cuando revertió sus cambios y realizó una actualización, su estación de trabajo coincidió con el repositorio pero la compilación aún estaba rota. ¿Por qué? Debido a que su estación de trabajo también era parte de una transacción comercial separada que tampoco estaba protegida por la semántica de ACID, a diferencia de su compromiso con el repositorio. Como no había actualizado su estación de trabajo para que coincidiera con el repositorio antes de ejecutar su compilación limpia, en realidad no estaba compilando los archivos fuente como existían en el repositorio. Si realizó dicha actualización, entonces descubriría que la compilación también falla en su estación de trabajo.

Ahora puedo exponer mi punto inicial: las transacciones tienen alcance / contexto que deben considerarse cuidadosamente. El hecho de que tenga una transacción ACID no significa que su lógica comercial sea segura, A MENOS QUE el alcance / contexto de la transacción ACID y la lógica comercial coincidan EXACTAMENTE. Si confía en alguna forma de transacción ACID de base de datos, pero hace NADA en la lógica de su negocio que no está cubierto por esa transacción de base de datos, entonces tiene una brecha que puede permitir un error comparable y catastrófico. Si puede obligar a su lógica de negocios a coincidir exactamente con su transacción de base de datos, entonces todo está bien. Si no es así, entonces probablemente necesite una transacción comercial por separado. Dependiendo de la naturaleza de la lógica desprotegida, es posible que deba implementar su propio mecanismo de transacción.

Entonces, la mensajería puede ser transaccional, pero el alcance es simplemente el mensaje. Respecto al ejemplo anterior, el contexto de Subversion es solo un compromiso individual al repositorio. Sin embargo, la transacción comercial es una construcción limpia, que implica un alcance mucho mayor. Este problema en particular generalmente se resuelve escribiendo una compilación limpia junto con una verificación limpia, idealmente usando una implementación de integración continua (por ejemplo, a través de CruiseControl o similar). En las estaciones de trabajo de los desarrolladores, se requiere que cada desarrollador ejerza la disciplina para realizar una actualización completa (o incluso una verificación limpia) antes de una compilación limpia.

Entonces, para recapitular, cada transacción tiene un alcance o contexto que limita su protección. Las transacciones comerciales a menudo incorporan lógica que excede el alcance de los mecanismos de transacción (como un motor de base de datos) que comúnmente utilizamos. Puede que tenga que compensar la diferencia. En raras ocasiones, incluso podría tener sentido escribir su propio mecanismo de transacción para hacerlo.

Diseñé una reescritura de un sistema empresarial crítico para una empresa modesta de noventa personas. Me pareció necesario implementar dicho mecanismo, y encontré que la experiencia es fácil, que vale la pena y es gratificante. Lo volvería a hacer, tal vez un poco más rápido, pero siempre me preguntaría por qué no podía limitarme a una transacción de base de datos.


Tenía la situación que necesitaba para tratar un sistema de archivos y una base de datos como una unidad transaccional.

En mi caso, solo necesitaba descargar un conjunto de archivos en el sistema de archivos. Lo hice creando directorios aleatorios cada vez, colocando los datos allí y almacenando el nombre del directorio en una tabla de base de datos. Por lo tanto, todo el trabajo de mi base de datos y el nombre del directorio en la tabla de la base de datos (= trabajo del sistema de archivos) se podrían realizar en una transacción de base de datos.

http://www.databasesandlife.com/atomic-operations-over-filesystem-and-database/


Creo que la razón por la que las transacciones solo se ven en las bases de datos es que, por definición, los sistemas que proporcionan transacciones se llaman bases de datos. Eso suena circular, así que debo elaborarlo.

El soporte de transacción es la característica que proporciona propiedades ACID . En términos sencillos, eso significa que una transacción es algo que permite 1. agrupar varias operaciones discretas en un paquete que tiene éxito como un todo o fallar como un todo 2. ocultar los cambios no confirmados a los usuarios concurrentes, de modo que 3. usuarios concurrentes tener en todo momento una vista "coherente" del sistema.

Los sistemas de archivos tradicionalmente ofrecen algún mecanismo de bloqueo, pero esto es diferente de proporcionar transacciones. Sin embargo, todos los sistemas de archivos tienen algunas propiedades atómicas. Por ejemplo, si tiene directorios /a/ y /b/ , y simultáneamente intenta ejecutar mv /a /b/a y mv /b /a/b , solo una de esas operaciones tendrá éxito, sin comprometer la integridad. Sin embargo, lo que generalmente les falta a los sistemas de archivos es la capacidad de agrupar múltiples operaciones en un solo paquete atómico aislado.

Una respuesta mencionó a Subversion. Todos los sistemas de control de versiones sanos tienen transacciones. Al comprometerse a múltiples archivos, el sistema aplica el commit por completo o lo rechaza por completo (excepto CVS, que no considero como cuerdo). La causa del rechazo es siempre un cambio simultáneo. Los implementadores del sistema de control de versiones son muy conscientes de mantener una base de datos.

Otra respuesta mencionó los sistemas de mensajería como transaccionales. No leí el material vinculado, pero la respuesta en sí misma menciona solo la entrega atómica de mensajes. Eso no es transacciones.

Nunca escuché hablar de Clojure antes de que Brian C. lo mencionara aquí. Me parece que de hecho es una implementación de transacciones fuera del contexto de una base de datos. Aquí el foco es el control de concurrencia, en lugar de mantener la coherencia de los datos duraderos.

Entonces, con la excepción de Clojure, parece que cualquier sistema que necesita transacciones usa una base de datos subyacente o se convierte en una base de datos.