jueves, 12 de diciembre de 2013

Read uncommitted


En esta entrada exploraremos cómo funciona el nivel de aislamiento READ UNCOMMITTED.

Antes de comenzar el ejercicio quisiera hacer notar que el nivel de aislamiento por defecto de SQL Server es READ COMMITTED, esto implica que no podemos leer la información sino hasta que ésta ha sido actualizada de forma definitiva (committed) en la base de datos o bien los cambios han sido deshechos a través de un rollback.

Por ejemplo, supongamos que la transacción 1 ejecuta la siguiente instrucción:
USE AdventureWorks GO BEGIN TRAN UPDATE Production.Product SET ListPrice += 1 WHERE ProductID = 1

Notamos que la transacción queda "abierta", es decir que no ha sido confirmada hacia la base de datos (committed) o deshecha (rollback), por lo tanto SQL Server mantendrá el bloqueo de tipo exclusivo sobre el producto cuyo id sea 1.

En otra ventana ejecutaremos la siguiente sentencia:
USE AdventureWorks GO BEGIN TRAN UPDATE Production.Product SET ListPrice += 1 WHERE ProductID = 1

Veremos que este query queda en espera debido a que el nivel de bloqueo que él requiere (READ COMMITTED) no le permite obtener la información que necesita debido a que la transacción 1 no ha finalizado. La transacción 1 tiene un bloqueo exclusivo que no es compatible con READ COMMITTED de otra transacción.

Esta información la podemos confirmar con la siguiente sentencia:
USE AdventureWorks GO SELECT DB_NAME(T.resource_database_id) AS database_name, OBJECT_NAME(P.[object_id]) FROM sys.dm_tran_locks T INNER JOIN sys.partitions P ON T.resource_associated_entity_id = P.hobt_id WHERE T.request_mode = 'X'

Veremos que se tiene un bloqueo exclusivo sobre algún elemento del objeto Production.Product. También se podría obtener la fila que está siendo bloqueada, pero perderíamos el enfoque de esta entrada.

Volvamos a la ventana de la transacción 1 y ejecutemos COMMIT, veremos que de forma casi inmediata la transacción 2 será desbloqueada y podrá obtener los datos que requiere.

¿Qué pasa cuando la información que queremos obtener es "inmutable"?, no quisiera utilizar la palabra inmutable en su totalidad debido a que en teoría los únicos datos inmutables de una base de datos son las llaves primarias, pero podemos suponer que el nombre de un producto es inmutable, sería muy extraño tener que actualizar el nombre de un producto. En este caso no requerimos que alguna otra transacción genere algún bloqueo sobre la lectura del Id y del Nombre del producto, por lo tanto, necesitamos leer los datos independientemente de los cambios que se estén realizando sobre ellos.

Antes de hacer cambios en el código, vamos a la ventana de la transacción 2 y ejecutamos COMMIT para no dejar transacciones abiertas (colgadas) en el manejador de bases de datos.

Volvamos a ejecutar el código de la transacción 1 para generar un bloqueo sobre el producto cuyo Id es 1, y vamos a cambiar un poco el código de la transacción 2:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED BEGIN TRAN SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID = 1

Podemos notar que ahora estamos estableciendo el nivel de aislamiento en READ UNCOMMITTED para poder leer datos que no han sido hechos "oficiales" en la base de datos. Si ejecutamos la transacción veremos que la información del nombre, producto y precio son inmediatamente devueltos.

Hasta ahora todo parecería que salió tal como lo deseamos, pero... ¿qué pasaría si necesitáramos realizar alguna acción tomando el precio del producto?, he ahí que vendría un fenómeno conocido como "dirty reads", eso quiere decir que podríamos leer un valor que no ha sido hecho oficial sobre la base de datos y que posiblemente su cambio pudiera ser deshecho, es decir que operaríamos con un valor que jamás debió ser tomado.

¿Qué debemos hacer?, dependerá de la operación y de los valores que queremos utilizar, deberemos establecer categorías de los datos que requieren un bloqueo exclusivo y también identificar los datos que pueden ser leídos durante una transacción de actualización.

Espero te haya resultado de utilidad esta entrada, nos vemos la siguiente.

No hay comentarios.:

Publicar un comentario