¿Cómo funciona una transacción SNAPSHOT?

Deja un comentario

Como recordarás, una transacción en Firebird puede tener uno de estos tres aislamientos:

  • READ COMMITED
  • SNAPSHOT
  • SNAPSHOT TABLE STABILITY

Los aislamientos le dicen al Firebird lo que debe hacer cuando una fila quiere ser actualizada (UPDATE) o borrada (DELETE) por más de una transacción al mismo tiempo.

Veamos un ejemplo:

  1. La transacción T1 empieza (su aislamiento es SNAPSHOT, y su modo de bloqueo es WAIT)
  2. La transacción T2 empieza (su aislamiento es SNAPSHOT)
  3. La transacción T2 actualiza (UPDATE) a una fila X de la tabla PRODUCTOS.
  4. La transacción T2 finaliza con un COMMIT
  5. La transacción T3 empieza (su aislamiento es SNAPSHOT)
  6. La transacción T3 también actualiza (UPDATE) a la misma fila X de la tabla PRODUCTOS
  7. La transacción T1 trata de actualizar (UPDATE) a la misma fila X de la tabla PRODUCTOS, pero como esa fila está bloqueada por la transacción T3 entonces deberá esperar hasta que la transacción T3 finalice.

Sin embargo, debemos notar que en este ejemplo la transacción T1 fallará siempre. ¿Por qué? Porque tendrá un conflicto con la transacción T3 si la transacción T3 finalizó con un COMMIT, o tendrá un conflicto con la transacción T2 si la transacción T3 finalizó con un ROLLBACK. O sea que, sin importar como termine la transacción T3 (con un COMMIT o con un ROLLBACK) la transacción T1 fallará.

Te puedes preguntar: ¿y por qué la transacción T1 debe esperar hasta que finalice la transacción T3? Después de todo, en ambos casos fallará, entonces ¿por qué la espera?

La respuesta está en que el Firebird solamente verifica la última versión de una fila para saber si ocurrió un conflicto o no. Si verificara la anteúltima versión entonces podría hacer fallar a la transacción T1 en el mismo momento en que hiciera un UPDATE, pero eso implicaría más trabajo y por lo tanto solamente verifica a la última versión.

Una transacción SNAPSHOT en el momento en que se inicia copia en su porción de la memoria RAM de la computadora la TIP (Transaction Inventory Page) conteniendo a todas las transacciones que están activas en ese momento. O sea, la transacción T2 conoce cuales son todas las transacciones que estaban activas cuando se inició la transacción T2, pero desconoce totalmente a las transacciones que se iniciaron después que ella y por lo tanto supone que están activas ya que evidentemente no habían finalizado cuando empezó la transacción T2. Cada transacción tiene un número único, que se guarda en la TIP. Cuando una transacción inicia bloquea a su propio número y lo desbloquea cuando finaliza (sea con un COMMIT o con un ROLLBACK). De esta manera es muy fácil saber si una transacción está activa o no. Si no se puede desbloquear su número, está activa. Si se puede desbloquear su número, no está activa.

Cuando una transacción SNAPSHOT trata de bloquear a una fila para hacerle un UPDATE o un DELETE, lo que puede ocurrir es lo siguiente:

  • Si la última versión de esa fila fue creada por una transacción que tiene un número menor y que no está en su copia de la TIP, el bloqueo tendrá éxito. ¿Por qué? porque como no está en su copia de la TIP y el número es menor, significa que una transacción anterior que insertó o actualizó a la fila ya finalizó con un COMMIT.
  • Si la última versión de una fila fue creada por una transacción cuyo número está en la TIP entonces debe verificar si esa transacción ya finalizó. ¿Y cómo lo verifica? Tratando de bloquear el número que esa otra transacción tiene en la TIP. Si lo consigue, la otra transacción ya finalizó y se puede bloquear a la fila con éxito.
  • Si el último COMMIT a la fila fue realizado por una transacción que tiene un número de transacción mayor, eso significa que esa otra transacción empezó después. Y por lo tanto, no se podrá bloquear a la fila.

Ejemplo:

Empieza una transacción, su número es 529, y en su copia de la TIP tiene a los números 521, 525, 526, 528. Eso significa que esas 4 transacciones están activas, aún no han finalizado ni con un COMMIT ni con un ROLLBACK.

La transacción cuyo número es 529 quiere hacer un UPDATE a una fila X de la tabla PRODUCTOS, el número de transacción que tiene la última versión de esa fila X es el 291. Como el número de transacción 291 no está en la copia de la TIP, eso significa que la transacción 291 (o una transacción anterior a ella) ya ha finalizado con un COMMIT y por lo tanto se podrá realizar el UPDATE con éxito a la fila X.

La transacción cuyo número es 529 quiere hacer un UPDATE a una fila X de la tabla PRODUCTOS, el número de transacción que tiene la última versión de esa fila es el 526. Como el número de transacción 526 está en la copia de la TIP, eso significa que la transacción 526 estaba activa cuando se inició la transacción 529. Pero ¿está activa ahora? quizás sí, quizás no, para verificarlo la transacción 529 trata de bloquear al número 526 en la TIP global, no en su propia copia de la TIP. Si consigue realizar el bloqueo, la transacción 526 ya no está activa y entonces podrá realizar el UPDATE con éxito. ¿Y si no consigue bloquear, qué hace? Eso dependerá del modo de bloqueo. Si es WAIT, seguirá intentando bloquear hasta tener éxito. Si es NO WAIT lanzará una excepción con un mensaje de error.

La transacción cuyo número es 529 quiere hacer un UPDATE a una fila X de la tabla PRODUCTOS, el número de transacción que tiene la última versión de esa fila es el 540. ¿Podrá la transacción 529 realizar el UPDATE? Depende. Si la transacción 540 finaliza con un COMMIT, no podrá. ¿Por qué no? Porque 540 es mayor que 529. Si la transacción 540 finaliza con un ROLLBACK entonces hay que buscar el número que tiene la última versión de esa fila X cuya transacción finalizó con un COMMIT. Si el último COMMIT a la fila X fue realizado por la transacción 520, la transacción 529 podrá realizar el UPDATE (porque 520 es menor que 529). Si el último COMMIT a la fila X fue realizado por la transacción 535, la transacción 529 no podrá realizar el UPDATE (porque 535 es mayor que 529).

Una transacción SNAPSHOT solamente puede actualizar (UPDATE) o borrar (DELETE) a las filas creadas por las transacciones que empezaron antes que ella.

Recuerda que el Firebird crea una nueva versión de una fila cada vez que se ejecuta el comando UPDATE o el comando DELETE en esa fila.

Sin importar como finalice la transacción (con un COMMIT o con un ROLLBACK) hay una nueva fila. Esto va creando filas inservibles (se les llama “basura”) y por ese motivo hay que limpiar a la Base de Datos de basura cada cierto tiempo.

Una fila tiene la siguiente forma:

| Nº de Transacción | Columna1 | Columna2 | Columna 3| etc.

Importante: Una transacción T1 (cuyo aislamiento es SNAPSHOT) puede actualizar (UPDATE) o borrar (DELETE) a una fila solamente cuando el Nº de Transacción que realizó el último COMMIT a esa fila es menor que el número de la transacción T1.

Artículos relacionados:

Entendiendo a las transacciones

Entendiendo a los identificadores de las transacciones

Modos de bloqueo de las transacciones

Bloqueos mortales

Lock conflict on no wait transaction. Deadlock

El índice del blog Firebird21

El foro del blog Firebird21

Como una transacción que terminó anormalmente es desechada

2 comentarios

Si una transacción terminó normalmente entonces es seguro que fue finalizada con un COMMIT o con un ROLLBACK.

Pero ¿y si terminó anormalmente?

Supongamos que ocurrió un corte de la energía eléctrica que apagó al Servidor mientras había una transacción Activa.

¿Cómo se terminará esa transacción?

Como la transacción no finalizó con un COMMIT ni con un ROLLBACK entonces continuará marcada como Activa aunque en realidad ya está muerta porque será imposible finalizarla con un COMMIT y ya nada se puede hacer con ella.

Pero en la Base de Datos sigue estando marcada como Activa.

Hay 2 formas de desechar (marcar como RolledBack)  a una transacción que finalizó anormalmente, y para entender esas dos formas debemos conocer que ocurre cuando una transacción inicia.

  1. Cada vez que una transacción inicia bloquea a su propio Identificador de transacción. O sea, obtiene acceso exclusivo a él. Por lo tanto, cuando se inicia la transacción T1 bloquea al identificador de la transacción T1. Si luego una transacción T2 quiere actualizar o borrar una fila primero verifica si la última versión de esa fila fue creada por una transacción que aún está Activa.  Si ése es el caso entonces trata de bloquear al Identificador de la transacción T1. Si lo consigue es porque la transacción T1 en realidad ya no está Activa, sino que está muerta. Entonces, la transacción T2 cambia el estado de la transacción T1 y lo marca como RolledBack.
  2. Cada vez que una transacción inicia, trata de obtener un acceso exclusivo a la Base de Datos. Si lo consigue es porque ninguna otra transacción está Activa. Y en ese caso cambia el estado de todas las transacciones que estaban marcadas como Activa y les coloca RolledBack. Tanto si consiguió el acceso exclusivo como si no lo consiguió, a continuación obtiene un acceso compartido a la Base de Datos. Por definición, si una transacción tiene acceso compartido entonces ninguna otra transacción podrá obtener un acceso exclusivo, aunque sí podrá tener un acceso compartido.

El método 1. tiene la ventaja de ser muy rápido, pero tiene la desventaja de que la transacción T1 (que finalizó anormalmente) puede estar marcada como Activa durante muchísimo tiempo si ninguna transacción T2 quiere actualizar o borrar las mismas filas que actualizó o borró la transacción T1.

El método 2. tiene la ventaja de que marca como RolledBack a todas las transacciones que finalizaron anormalmente, y lo hace de una sola vez. Su desventaja es que en bases de datos muy grandes y que tienen muchas transacciones terminadas anormalmente se demora bastante más tiempo.

Entonces ¿qué ocurre cuando se inicia el Servidor del Firebird?

Que la primera transacción intentará obtener un acceso exclusivo a la Base de Datos. Si lo consigue (siempre lo debería conseguir), marcará a todas las transacciones que estaban Activa como RolledBack. Y por lo tanto en la Base de Datos ninguna transacción continuará estando marcada incorrectamente como Activa. Eso está muy bien, así debe ser.

El corolario es que para asegurarnos de no tener transacciones muertas (o sea, transacciones marcadas como Activa pero que en realidad no pueden ser finalizadas con un COMMIT) debemos detener y luego reiniciar al Servidor del Firebird.

Conclusión:

Cuando una transacción se inicia su estado siempre es Activa. Si luego finaliza anormalmente (por un corte de la energía eléctrica, por ejemplo) continúa marcada como Activa aunque en realidad está muerta ya que no puede finalizar con un COMMIT.

Está mal que esté marcada como Activa, eso no es lo correcto, y debe corregirse.

Para corregir el estado de la transacción existen dos métodos que emplea el Firebird:

Método 1. Cuando una transacción T2 quiere actualizar o borrar una fila cuya última versión fue creada por una transacción T1 que figura como Activa aunque sin estar Activa, actualiza el estado de la transacción T1 y le pone RolledBack, tal y como debe ser.

Método 2. Cuando una transacción se inicia, trata de obtener acceso exclusivo a la Base de Datos. Si lo consigue es porque no existe otra transacción Activa y entonces cambia el estado de todas las transacciones que estaban marcadas como Activa (incorrectamente, desde luego) a RolledBack, tal y como debe ser.

La desventaja del Método 1. es que una transacción T1 puede continuar marcada como Activa durante mucho tiempo, si ninguna otra transacción T2 quiere actualizar o borrar esas mismas filas. La desventaja del Método 2. es que solamente funciona cuando no hay otras transacciones activas, por lo tanto es inaplicable en Servidores que están encendidos 24/7/365.

La mejor manera de asegurarnos de no tener transacciones cuyo estado está marcado como Activa aunque en realidad están muertas, es detener y luego reiniciar el Servidor del Firebird.

Artículos relacionados:

Entendiendo a las transacciones

Entendiendo los identificadores de las transacciones

Entendiendo las páginas de la Base de Datos

El índice del blog Firebird21

El foro del blog Firebird21

 

 

 

Respuestas a más preguntas sobre transacciones (5)

4 comentarios

Bueno, aquí están las respuestas correctas. ¿Estás respondiendo a las preguntas? Si no lo has hecho, … deberías hacerlo. Así sabrás realmente que sabes y que no sabes sobre las transacciones del Firebird.

Pregunta 1. Si una transacción bloquea a una fila justo cuando va a realizar un UPDATE en esa fila, esa transacción es:

[Optimista]     [Pesimista]

La transacción es Optimista. Las transacciones optimistas bloquean a una fila justo en el instante en que deben realizar un UPDATE o un DELETE a esa fila. En cambio, las transacciones pesimistas bloquean a la fila cuando la transacción se inicia, lo cual pudo haber ocurrido mucho antes del UPDATE o del DELETE.

Por eso el nombre de optimistas y de pesimistas. La optimista supone que cuando quiera actualizar la fila podrá hacerlo porque ninguna otra transacción la tendrá bloqueada. La pesimista bloquea la fila al iniciar la transacción para que cuando necesite actualizarla pueda hacerlo ya que ninguna otra transacción la habrá bloqueado.

Pregunta 2. En Firebird es preferible que las transacciones sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

Es altamente preferible que las transacciones sean Optimistas. ¿Por qué? Porque Firebird usa versionado múltiple de registros, es decir que cada operación de UPDATE o de DELETE crea un nuevo registro en la tabla (cada registro puede tener muchas versiones). Eso es así, siempre fue así, y nunca cambiará. Si una transacción es pesimista entonces durante mucho tiempo impide a las demás transacciones realizar un UPDATE o un DELETE a la fila (o filas) que esa transacción pesimista bloqueó.

Pregunta 3. Si se desea que aunque varios usuarios estén insertando datos simultáneamente no haya números faltantes en la secuencia, las transacciones deben ser:

[Optimistas]     [Pesimistas]     [Es indiferente]

Las transacciones deben ser Pesimistas. Este es casi el único caso en que se justifica que las transacciones sean pesimistas. Si fueran optimistas entonces si una transacción termina con un ROLLBACK dejará un hueco en la secuencia.

Pregunta 4. Para que una transacción bloquee a una fila el menor tiempo posible, esa transacción debe ser:

[Optimista]     [Pesimista]     [Es indiferente]

La transacción debe ser Optimista. Las transacciones optimistas bloquean a una fila en el momento de realizarle un UPDATE o un DELETE y la desbloquean inmediatamente después. En cambio las transacciones pesimistas bloquean a la fila en el momento de iniciarse la transacción y la desbloquean en el momento de finalizar la transacción.

Pregunta 5. Si siempre un solo usuario usará una Base de Datos, es preferible que las transacciones en esa Base de Datos sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

En este caso es preferible que las transacciones sean Pesimistas porque eso le ahorrará al Firebird el trabajo de estar verificando si una fila está bloqueada por otra transacción o no. Por lo tanto, la transacción finalizará más rápido.

Pregunta 6. Si muchos usuarios usarán una Base de Datos al mismo tiempo, es preferible que las transacciones en esa Base de Datos sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

Es altamente preferible que las transacciones sean Optimistas porque son las que mantienen bloqueadas a las filas el menor tiempo posible.

Pregunta 7. Si a una Base de Datos se accederá por Internet, es preferible que las transacciones en esa Base de Datos sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

En este caso ya es prácticamente obligatorio que las transacciones sean Optimistas porque si una transacción T1 tiene bloqueada de forma pesimista a una fila y la transacción T2 quiere actualizar esa fila, podría tardar una eternidad en hacerlo.

Como la distancia entre el Servidor y la computadora del usuario es muchísimo mayor cuando el acceso es por Internet, comparado con el acceso dentro de una red local, todas las operaciones ya de por sí son más lentas.Y si a eso además le sumamos que las transacciones son pesimistas, entonces…sólo resta sentarse, ponerse cómodo, … y esperar.

Artículos relacionados:

 Entendiendo a las transacciones

3 preguntas sobre transacciones

Respuestas a las 3 preguntas sobre transacciones

Más preguntas sobre transacciones (2)

Respuestas a más preguntas sobre transacciones (2)

Más preguntas sobre transacciones (3)

Respuestas a más preguntas sobre transacciones (3)

Más preguntas sobre transacciones (4)

Respuestas a más preguntas sobre transacciones (4)

Más preguntas sobre transacciones (5)

El índice del blog Firebird21

El foro del blog Firebird21

Más preguntas sobre transacciones (5)

10 comentarios

Y continuamos haciendo preguntas sobre transacciones, como puedes ver, hay un montón de preguntas que se pueden hacer porque las transacciones son algo bastante complejo, por eso a mucha gente le cuesta entenderlas pero … hay que entenderlas, sí o sí.

Pregunta 1. Si una transacción bloquea a una fila justo cuando va a realizar un UPDATE en esa fila, esa transacción es:

[Optimista]     [Pesimista]

Pregunta 2. En Firebird es preferible que las transacciones sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

Pregunta 3. Si se desea que aunque varios usuarios estén insertando datos simultáneamente no haya números faltantes en la secuencia, la transacción debe ser:

[Optimista]     [Pesimista]     [Es indiferente]

Pregunta 4. Para que una transacción bloquee a una fila el menor tiempo posible, esa transacción debe ser:

[Optimista]     [Pesimista]     [Es indiferente]

Pregunta 5. Si siempre un solo usuario usará una Base de Datos, es preferible que las transacciones en esa Base de Datos sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

Pregunta 6. Si muchos usuarios usarán una Base de Datos al mismo tiempo, es preferible que las transacciones en esa Base de Datos sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

Pregunta 7. Si a una Base de Datos se accederá por Internet, es preferible que las transacciones en esa Base de Datos sean:

[Optimistas]     [Pesimistas]     [Es indiferente]

Artículos relacionados:

Entendiendo a las transacciones

3 preguntas sobre transacciones

Respuestas a las 3 preguntas sobre transacciones

Más preguntas sobre transacciones (2)

Respuestas a más preguntas sobre transacciones (2)

Más preguntas sobre transacciones (3)

Respuestas a más preguntas sobre transacciones (3)

Más preguntas sobre transacciones (4)

Respuestas a más preguntas sobre transacciones (4)

El índice del blog Firebird21

El foro del blog Firebird21

Respuestas a más preguntas sobre transacciones (4)

1 comentario

¿Estás respondiendo las preguntas sobre transacciones?

Si lo estás haciendo, felicitaciones, si no lo estás haciendo, …. deberías, para aprender más.

Veamos cuales son las respuestas correctas del artículo: Más preguntas sobre transacciones (4)

Pregunta 1. Si una transacción solamente hará SELECTs ¿cuál debe ser su acceso?

[READ ONLY]     [READ WRITE]     [Es indiferente]

La respuesta correcta: Es indiferente. ¿Por qué? porque en ambos casos podrá hacer los SELECTs, sin embargo es preferible que sea READ ONLY porque las transacciones READ ONLY terminan más rápido que las transacciones READ WRITE debido a que el Firebird realiza menos tareas, pero no es obligatorio que sea READ ONLY.

Pregunta 2. Si una transacción solamente hará INSERTs ¿cuál debe ser su acceso?

[READ ONLY]     [READ WRITE]     [Es indiferente]

En este caso la transacción debe ser READ WRITE porque no se puede realizar un INSERT (ni un UPDATE, ni un DELETE) en las transacciones READ ONLY.

Pregunta 3. Si una transacción hará SELECTs e INSERTs, ¿cuál debe ser su acceso?

[READ ONLY]     [READ WRITE]     [Es indiferente]

Debe ser READ WRITE sí o sí, porque no se puede realizar un INSERT (ni un UPDATE, ni un DELETE) en una transacción READ ONLY.

Pregunta 4. Si una transacción quiere conocer lo que otras transacciones que finalizaron con COMMIT hicieron. ¿Cuál debe ser su aislamiento?

[READ COMMITTED]     [SNAPSHOT]     [Es imposible, nunca puede conocer lo que otras transacciones hicieron]

El aislamiento READ COMMITTED permite conocer lo que otras transacciones que ya finalizaron con un COMMIT hicieron. El aislamiento SNAPSHOT no permite tal cosa.

Pregunta 5. Si una transacción T1 ha bloqueado a una fila y una transacción T2 quiere actualizar a esa misma fila. ¿Cuál debe ser el modo de bloqueo de la transacción T2 para que pueda hacerlo?

[WAIT]     [NO WAIT]     [Cualquiera, es indiferente]     [Nunca la transacción T2 podrá actualizar esa fila]

Debe ser WAIT y entonces la transacción T2 esperará hasta que la transacción T1 finalice. Si el modo de bloqueo de la transacción T2 es NO WAIT entonces inmediatamente obtendrá una excepción y nunca podrá actualizar a esa fila.

Pregunta 6. Si una transacción T1 ha bloqueado a una fila, y quieres que la transacción T2 pueda ver la última versión confirmada de esa fila. ¿Cuál versión de registro debe tener la transacción T2?

[RECORD_VERSION]     [NO RECORD_VERSION]     [Es indiferente]

Debes usar RECORD_VERSION, porque en este caso la transacción T2 podrá ver la última versión confirmada de la fila. Si usas NO RECORD_VERSION entonces la fila que actualizó la transacción T1 será inaccesible para la transacción T2, inclusive para lectura.

Pregunta 7. Si una transacción T1 ha bloqueado una fila y no quieres que la transacción T2 pueda ni siquiera ver la última versión confirmada de esa fila ¿Cuál versión de registro debe tener la transacción T2?

[RECORD_VERSION]     [NO RECORD_VERSION]     [Es indiferente]

Debe ser NO RECORD_VERSION porque en este caso si una fila está bloqueada por una transacción las demás transacciones no pueden acceder a esa fila, ni siquiera para lectura.

Pregunta 8. Si una transacción quiere tener acceso exclusivo a todas las tablas que utiliza ¿puede hacerlo?

[Sí]     [No]

La respuesta es . En ese caso su aislamiento debe ser SNAPSHOT TABLE STABILITY. Si la transacción pudo iniciarse (no siempre podrá, otras transacciones podrían impedírselo) entonces tendrá acceso exclusivo.

Pregunta 9. Si una transacción quiere tener acceso exclusivo solamente a algunas de las tablas que utiliza ¿puede hacerlo?

[Sí]     [No]

La respuesta es . En ese caso debe escribir RESERVING y la lista de las tablas a las que quiere acceder de forma exclusiva.

Artículos relacionados:

Entendiendo a las transacciones

3 preguntas sobre transacciones

Respuestas a las 3 preguntas sobre transacciones

Más preguntas sobre transacciones (2)

Respuestas a más preguntas sobre transacciones (2)

Más preguntas sobre transacciones (3)

Respuestas a más preguntas sobre transacciones (3)

Más preguntas sobre transacciones (4)

El índice del blog Firebird21

El foro del blog Firebird21

NO RECORD_VERSION es el defecto en el aislamiento READ COMMITTED

5 comentarios

Esto es importantísimo para recordar y tener en cuenta.

En ambas versiones del libro “The Firebird Book” de Helen Borrie, que es la “biblia” del Firebird dice que si una transacción tiene el aislamiento READ COMMITTED su versionado por defecto es RECORD_VERSION.

Eso no es así (se equivocó la “biblia”) porque en realidad el versionado por defecto es NO RECORD_VERSION, tal y como se establece en el documento “Interbase 6.0 Embedded SQL Guide”, página 67 (está en inglés) y en el documento “Firebird 2.5 Language Reference”, página 348 (está en ruso).

Como en “The Firebird Book” decía que el versionado por defecto era RECORD_VERSION el autor de este blog así lo creyó y lo escribió en un artículo previo (que ya está corregido también).

Entonces y para asegurarnos … verifiquemos cual es el versionado por defecto.

Para ello abriremos dos instancias de ISQL y veremos lo que sucede cuando se actualiza una fila de una tabla.

RECORD_VERSION

Captura 1. Si haces clic en la imagen la verás más grande

Como se puede ver en la Captura 1., cuando no se especifica el versionado el Firebird asume por defecto que se trata de NO RECORD_VERSION. Eso lo podemos comprobar haciendo el UPDATE de una fila en la instancia ISQL 1 y luego queriendo consultar esa misma fila en la instancia ISQL 2. El mensaje “Lock conflict on no wait transaction….” nos está diciendo que ocurrió un conflicto con otra transacción. ¿Por qué? Porque hay otra transacción que hizo un UPDATE o un DELETE a la fila cuyos datos quisimos consultar y el aislamiento de nuestra transacción es READ COMMITTED y su versionado evidentemente es NO RECORD_VERSION, por eso obtuvimos el mensaje de error.

Establezcamos ahora que la transacción sea READ COMMITTED y su versionado RECORD_VERSION y veamos lo que ocurre.

¿Qué ocurrió? Pues que nuestro SELECT que involucra a la fila que la instancia ISQL 1 está actualizando, esta vez sí tuvo éxito. Como podemos ver en la última fila de la Captura 1., obtuvimos lo que se encuentra en la última versión confirmada (es decir, que finalizó con un COMMIT) de esa fila.

Conclusión:

Es muy importante recordar que por defecto el Firebird abre a las transacciones READ COMMITTED con el versionado de NO RECORD_VERSION y que ese es el versionado que provoca más conflictos.

Como podemos ver en la Captura 1. el versionado NO RECORD_VERSION provocó un conflicto, en cambio el versionado RECORD_VERSION pasó sin problema.

De todo esto podemos sacar dos enseñanzas:

  1. No confiar ciegamente en todo lo que dicen los libros (o los blogs, je), sus autores pueden equivocarse.
  2. Si abrimos una transacción READ COMMITTED y no especificamos el versionado, éste será NO RECORD_VERSION y ese versionado provoca muchos conflictos.

Artículos relacionados:

Entendiendo a las transacciones

El índice del blog Firebird21

El foro del blog Firebird

Más preguntas sobre transacciones (4)

4 comentarios

Parece que muchos tienen miedo de responder a las preguntas que plantea este blog ¿por qué será? Son sólo preguntas, y si se responde incorrectamente cuando se conoce la respuesta correcta nunca más se la olvida.

En ajedrez hay un viejo dicho: “se aprende más de una partida perdida que de cien partidas ganadas”

¿Por qué?

Porque si te interesa ser bueno en ese juego, cuando pierdes una partida, la miras y la analizas una y otra vez, para descubrir tus errores y corregirlos y nunca más volver a cometerlos. En cambio si ganaste, ni te molestas en reproducir la partida ¿para qué? la ganaste y a otra cosa.

Análogamente si quieres ser bueno en Firebird deberías responder a todas las preguntas planteadas. ¿Te equivocaste en algunas? Eso no es malo, porque cuando leas las respuestas correctas ya no las olvidarás.

Bueno, luego de esa larga introducción, continuemos:

Pregunta 1. Si una transacción solamente hará SELECTs ¿cuál debe ser su acceso?

[READ ONLY]     [READ WRITE]     [Es indiferente]

Pregunta 2. Si una transacción solamente hará INSERTs ¿cuál debe ser su acceso?

[READ ONLY]     [READ WRITE]     [Es indiferente]

Pregunta 3. Si una transacción hará SELECTs e INSERTs, ¿cuál debe ser su acceso?

[READ ONLY]     [READ WRITE]     [Es indiferente]

Pregunta 4. Si una transacción quiere conocer lo que otras transacciones que finalizaron con COMMIT hicieron. ¿Cuál debe ser su aislamiento?

[READ COMMITTED]     [SNAPSHOT]     [Es imposible, nunca puede conocer lo que otras transacciones hicieron]

Pregunta 5. Si una transacción T1 ha bloqueado a una fila y una transacción T2 quiere actualizar a esa misma fila. ¿Cuál debe ser el modo de bloqueo de la transacción T2 para que pueda hacerlo?

[WAIT]     [NO WAIT]     [Cualquiera, es indiferente]     [Nunca la transacción T2 podrá actualizar esa fila]

Pregunta 6. Si una transacción T1 ha bloqueado a una fila, y quieres que la transacción T2 pueda ver la última versión confirmada de esa fila. ¿Cuál versión de registro debe tener la transacción T2?

[RECORD_VERSION]     [NO RECORD_VERSION]     [Es indiferente]

Pregunta 7. Si una transacción T1 ha bloqueado una fila y no quieres que la transacción T2 pueda ni siquiera ver la última versión confirmada de esa fila ¿Cuál versión de registro debe tener la transacción T2?

[RECORD_VERSION]     [NO RECORD_VERSION]     [Es indiferente]

Pregunta 8. Si una transacción quiere tener acceso exclusivo a todas las tablas que utiliza ¿puede hacerlo?

[Sí]     [No]

Pregunta 9. Si una transacción quiere tener acceso exclusivo solamente a algunas de las tablas que utiliza ¿puede hacerlo?

[Sí]     [No]

Artículos relacionados:

Entendiendo a las transacciones

3 preguntas sobre transacciones

Respuestas a las 3 preguntas sobre transacciones

Más preguntas sobre transacciones (2)

Respuestas a más preguntas sobre transacciones (2)

Más preguntas sobre transacciones (3)

Respuestas a más preguntas sobre transacciones (3)

El índice del blog Firebird21

El foro del blog Firebird21

Older Entries