¿Qué sucede si no confirma una transacción en una base de datos (por ejemplo, SQL Server)?

108

Supongamos que tengo una consulta:

begin tran
-- some other sql code

Y luego me olvido de comprometerme o retroceder.

Si otro cliente intenta ejecutar una consulta, ¿qué pasaría?

Charbel
fuente

Respuestas:

148

Siempre que no COMPRUEBE o RETROCEDA una transacción, todavía está "ejecutándose" y potencialmente manteniendo bloqueos.

Si su cliente (aplicación o usuario) cierra la conexión a la base de datos antes de comprometerse, las transacciones que aún se estén ejecutando se revertirán y finalizarán.

marc_s
fuente
1
mmm, ok, me di cuenta de que esto estaba creando algún tipo de bloqueo. No estaba seguro de que cerrar la conexión realmente me sacaría de este estado. el problema era que recibía un error cuando intentaba comprometerme. ahora cerré la conexión y todo funcionó.
Charbel
12
Nota al margen: si usa Management Studio, cerrar la ventana de consulta cerrará la conexión
Joe Phillips
3
@BradleyDotNET: sí, definitivamente
marc_s
2
Tenga en cuenta que SQL Server Management Studio se confirma automáticamente si cierra la ventana / conexión de consulta, de forma predeterminada.
Nuno
1
Tenga en cuenta que cuando el cliente cierra la conexión mientras una transacción está activa, no siempre se revierte; esto depende del cliente y de la base de datos. Por ejemplo, cuando una aplicación Java cierra una conexión a una base de datos de Oracle, cualquier conexión abierta se confirma automáticamente.
AviD
38

De hecho, puede probar esto usted mismo, eso debería ayudarlo a tener una idea de cómo funciona.

Abra dos ventanas (pestañas) en Management Studio, cada una de ellas tendrá su propia conexión a SQL.

Ahora puede comenzar una transacción en una ventana, hacer algunas cosas como insertar / actualizar / eliminar, pero aún no confirmar. luego, en la otra ventana, puede ver cómo se ve la base de datos desde fuera de la transacción. Dependiendo del nivel de aislamiento, la tabla puede bloquearse hasta que se confirme la primera ventana, o es posible que (no) vea lo que ha hecho la otra transacción hasta ahora, etc.

Juegue con los diferentes niveles de aislamiento y sin pistas de bloqueo para ver cómo afectan los resultados.

Vea también lo que sucede cuando arroja un error en la transacción.

Es muy importante entender cómo funciona todo esto o te quedarás perplejo por lo que hace sql, muchas veces.

¡Que te diviertas! GJ.

gjvdkamp
fuente
ok, pero ¿se escribirá la transacción para que se registre al menos antes de emitir el compromiso? Por ejemplo, digamos que quiero iniciar una transacción, ejecutar un comando de inserción y "hacer otra cosa" antes de ejecutar el compromiso. ¿Mi comando de inserción se escribirá en el registro? de esa manera, si el servidor falla antes de ejecutar la confirmación ... puede volver a donde estaba y puedo emitir la confirmación más tarde (cuando termine de hacer "otra cosa").
user1870400
16

Las transacciones están diseñadas para ejecutarse completamente o no ejecutarse en absoluto. La única forma de completar una transacción es comprometerse, cualquier otra forma resultará en una reversión.

Por lo tanto, si comienza y luego no se compromete, se revertirá al cerrar la conexión (ya que la transacción se interrumpió sin marcar como completa).

Piskvor salió del edificio
fuente
Así debería ser, pero no siempre es así.
FalcoGer
... como MyISAM de mySQL, que no admite transacciones, seguro.
Piskvor salió del edificio el
3

depende del nivel de aislamiento de la transacción entrante.

Explicación del aislamiento de transacciones SQL

Xhalent
fuente
6
El comportamiento de las transacciones no depende del nivel de aislamiento. La cantidad de bloqueos que pueden causar sí.
marc_s
Estoy bastante seguro de que los datos que puede leer una conexión definitivamente dependen del nivel de aislamiento. Si tiene el aislamiento establecido en READ UNCOMMITTED, puede leer los datos que aún no se han confirmado y, de hecho, es posible que se reviertan en algún momento de la pista, pero esto garantiza que no haya bloqueo. Si ha READ COMMITTED como su nivel de aislamiento, entonces no puede leer filas no confirmadas; el segundo cliente se bloqueará a menos que use SNAPSHOT.
Xhalent
2

Cuando abre una transacción, nada se bloquea por sí solo. Pero si ejecutas algunas consultas dentro de esa transacción, dependiendo del nivel de aislamiento, algunas filas, tablas o páginas se bloquean por lo que afectará a otras consultas que intentan acceder a ellas desde otras transacciones.

trébol rojo
fuente
1

Ejemplo de transacción

comenzar tran tt

Tus declaraciones SQL

si ocurrió un error rollback tran tt else commit tran tt

Mientras no haya ejecutado la transacción de confirmación, los datos no se cambiarán

usuario3386471
fuente
1
Tenga en cuenta que las transacciones de nombres no solo son innecesarias en MS SQL, sino que pueden dar una falsa sensación de control. BEGIN TRAN X ... BEGIN TRAN Y ... ROLLBACK Yno funciona, por ejemplo. Ver stackoverflow.com/questions/1273376/…
0

Además de los posibles problemas de bloqueo que puede causar, también encontrará que sus registros de transacciones comienzan a crecer, ya que no se pueden truncar más allá del LSN mínimo para una transacción activa y, si está utilizando el aislamiento de instantáneas, su almacén de versiones en tempdb crecerá durante razones similares.

Puede utilizar dbcc opentranpara ver los detalles de la transacción abierta más antigua.

Martin Smith
fuente
0

Cualquier transacción no iniciada dejará el servidor bloqueado y otras consultas no se ejecutarán en el servidor. Debe revertir la transacción o confirmarla. El cierre de SSMS también terminará la transacción, lo que permitirá que se ejecuten otras consultas.

Josh Moorish
fuente
-4

El comportamiento no está definido, por lo que debe establecer explícitamente una confirmación o una reversión:

http://docs.oracle.com/cd/B10500_01/java.920/a96654/basic.htm#1003303

"Si el modo de confirmación automática está deshabilitado y cierra la conexión sin comprometer o revertir explícitamente sus últimos cambios, entonces se ejecuta una operación COMMIT implícita".

Hsqldb hace una reversión

con.setAutoCommit(false);
stmt.executeUpdate("insert into USER values ('" +  insertedUserId + "','Anton','Alaf')");
con.close();

el resultado es

2011-11-14 14: 20: 22,519 principal INFO [SqlAutoCommitExample: 55] [AutoCommit habilitado = falso] 2011-11-14 14: 20: 22,546 principal INFO [SqlAutoCommitExample: 65] [Se encontraron 0 # usuarios en la base de datos]

Bernd Schatz
fuente
2
Esto puede ser cierto para Oracle (no tengo idea), pero el interlocutor pregunta sobre MS-SQL
PaulG
La primera cita se aplica al controlador JDBC, no al servidor.
djechlin