Preparación para el examen 730 Fundamentos DB2 9, Parte 6: Concurrencia de datos

Este tutorial le introducirá al concepto de consistencia de datos y a los diferentes mecanismos utilizados por DB2 for Linux, UNIX y Windows para mantener la consistencia entornos de base de datos tanto individuales como multi-usuario. Este es el último tutorial de una serie de seis tutoriales que usted puede utilizar para prepararse para la Certificación en Fundamentos DB2 para Linux, UNIX y Windows (Examen 730).

Roger E. Sanders, Consultant Corporate Systems Engineer, EMC Corporation

Author1 photoRoger Sanders es Ingeniero de Sistemas Consultor Corporativo en el equipo Integrated Customer Operations en EMC. Cuanta con nueve años de experiencia en la industria del almacenamiento y ha estado trabajando con DB2 para Linux, UNIX y Windows desde que se introdujeron por primera vez. Roger ha escrito para en IDUG Solutions Journal and Certification Magazine, ha sido autor de 20 libros sobre DB2, y ha hecho numerosas presentaciones en conferencias, y también ha impartido clases sobre DB2. Ha escrito bastantes artículos y tutoriales para developerWorks y para IBM Data Management Magazine.



16-02-2012

Antes de comenzar

Sobre esta serie

¿Está pensando en obtener la certificación en fundamentos DB2 (Examen 730)? Si es así, ha llegado al lugar correcto. Esta serie de siete tutoriales de preparación para la certificación DB2 cubre todo lo básico (los temas que necesitará entender antes de leer la primera pregunta del examen). Incluso si usted no está pensando en obtener la certificación justo ahora, este conjunto de tutoriales es un excelente lugar para comenzar a saber qué hay de nuevo en DB2 9.

Acerca de este tutorial

Este tutorial le introducirá al concepto de consistencia de datos y a los diferentes mecanismos utilizados por DB2 for Linux, UNIX y Windows para mantener la consistencia de datos en entornos de base de datos tanto individuales como multi-usuario. En este tutorial usted aprenderá:

  • Qué es la consistencia de datos
  • Qué son las transacciones y cómo se inician y se terminan
  • Cómo se aíslan las transacciones entre sí en un entorno multi-usuario
  • Cómo DB2 for Linux, UNIX y Windows proporciona control de concurrencia mediante el uso de bloqueos
  • Qué tipos de bloqueos están disponible y cómo se adquieren
  • Cuáles factores influencian el bloqueo

Este tutorial de una serie de siete tutoriales que usted puede utilizar para prepararse para la Certificación en Fundamentos DB2 9 (Examen 730). El material en este tutorial principalmente cubre los objetivos de la Sección 6 del examen, titulada "Concurrencia de Datos". Usted puede ver estos objetivos en: http://www.ibm.com/certify/tests/obj730.shtml.

Usted necesita una copia de DB2 for Linux, UNIX y Windows para completar este tutorial. Sin embargo, usted puede descargar una versión gratuita de prueba de DB2 para Linux, UNIX y Windows Enterprise Edition.

Objetivos

Después de completar este tutorial, usted deberá estar en capacidad de:

  • Identificar los factores que influencian el bloqueo
  • Hacer una lista de objetos sobre los cuales se puedan obtener bloqueos
  • Identificar las características de los bloqueos DB2
  • Identificar el nivel de aislamiento que se debería usar para una situación dada

Requisitos previos

Para entender parte del material presentado en este tutorial, usted debe estar familiarizado con los siguientes términos:

  • Objeto: Cualquier cosa de una base de datos que pueda ser creada o manipulada con SQL (e.g., tablas, vistas, índices, paquetes).

  • Tabla: Es una estructura lógica que se utiliza para presentar datos como una colección de filas no ordenadas con un número arreglado de columnas. Cada columna contiene un conjunto de valores, cada valor de mismo tipo de datos (o de un subtipo del tipo de datos de columna); las definiciones de las columnas constituyen la estructura de tabla y las filas contienen los datos efectivos de tabla.

  • Registro: Es la representación de almacenamiento de una tabla.

  • Campo: Es la representación de almacenamiento de una columna de una tabla.

  • Valor: Es un elemento de datos específico que se puede encontrar en cada intersección de una fila o columna de una tabla de base de datos.

  • Lenguaje de consulta estructurado (SQL): Es un lenguaje estandarizado utilizado para definir objetos y manipular datos de una base de datos relacional. (Para más sobre SQL, consulte el cuarto tutorial de esta serie.

  • Optimizador DB2: Es un componente del pre-compilador SQL que selecciona un plan de acceso para un enunciado SQL Data Manipulation Language (DML), mediante el modelaje del costo de ejecución de varios planes de acceso alternativos, y seleccionando el de mínimo costo estimado.

Requisitos de sistema

Usted no necesita tener una copia DB2 para completar este tutorial. No obstante, aprovechará mejor el tutorial si descarga la versión gratuita de prueba IBM DB2 for Linux, UNIX, and Windows para trabajar junto con este tutorial.


Transacciones

Entendiendo la consistencia de datos

¿Qué es la consistencia de datos? La mejor forma de responder esta pregunta es mediante un ejemplo. Suponga que su compañía posee una cadena de restaurantes y que usted tiene una base de datos que está diseñada para hacer seguimiento de los suministros almacenados en cada uno de esos restaurantes. Para facilitar el proceso de compras-suministros, su base de datos contiene una tabla de inventario para cada restaurante de la cadena. Cada vez que un restaurante recibe o utiliza suministros, la tabla de inventario correspondiente de ese restaurante es modificada para reflejar los cambios.

Ahora, suponga que algunas botellas de salsa de tomate son movidas físicamente de un restaurante a otro. Para representar acertadamente este movimiento en el inventario, el valor del conteo de la botella de salsa de tomate almacenada en la tabla del restaurante que las cede, necesita reducirse, y el valor del conteo de botellas de salsa de tomate almacenado en la tabla del restaurante que las recibe debe aumentarse. Si un usuario disminuye el conteo de botellas de salsa de tomate en la tabla de inventario del restaurante que las cede, pero no aumenta el conteo en la tabla de inventario del restaurante que las recibe, los datos se tornarán inconsistentes (ahora el conteo total de botellas de salsa de tomate de la cadena de restaurantes ya no es acertado).

Los datos de una base de datos pueden tornarse inconsistentes si algún usuario olvida realizar todos los cambios necesarios (como en el ejemplo anterior), si el sistema colapsa mientras el usuario está en la mitad de un cambio, o si una aplicación de base de datos se detiene por alguna razón. La inconsistencia también se puede presentar cuando varios usuarios están accediendo a las mismas bases de datos al mismo tiempo. En un esfuerzo para evitar la inconsistencia de los datos, particularmente en entornos multi-usuario, se han incorporado en el DB2 for Linux, Unix y Windows los siguientes mecanismos para soporte de consistencia:

  • Transacciones
  • Niveles de aislamiento
  • Bloqueos

Transacciones y límites de transacciones

Una transacción (también conocida como una unidad de trabajo ) es una secuencia recuperable de una o más operaciones SQL, agrupadas como una sola unidad, normalmente dentro de un proceso de aplicación. El inicio y terminación de una transacción definen los puntos de consistencia de una base de datos; o los efectos de todas las operaciones SQL efectuadas dentro de una transacción son aplicados (confirmados), o los efectos de todas las operaciones SQL efectuadas se deshacen completamente y se descartan (revertidos).

Con las aplicaciones y scripts SQL incorporados, ejecutados desde el Command Center, el Script Center o el Command Line Processor, las transacciones son iniciadas automáticamente la primera vez que se ejecuta un enunciado SQL ejecutable, bien sea después que se establezca una conexión con la base de datos o bien después de que se haya terminado una transacción existente. Una vez iniciada, una transacción debe ser terminada explícitamente por el usuario o por la aplicación que la inició, a menos que un proceso conocido como confirmación automática esté siendo utilizado (en cuyo caso cada enunciado SQL individual ingresado para ejecución es tratado como una transacción individual que es confirmada implícitamente tan pronto se ejecuta).

En la mayoría de los casos, las transacciones son terminadas ejecutando los enunciados COMMIT o ROLLBACK . Cuando se ejecuta el enunciado COMMIT , todos los cambios que se hayan efectuado a la base de datos desde que se inició la transacción se tornarán permanentes (es decir, se escriben en el disco). Cuando se ejecuta el enunciado ROLLBACK , todos los cambios que se hayan efectuado a la base de datos desde que se inició la transacción se regresarán al estado en que estaban antes de que la transacción iniciara. En cualquier caso, se garantiza que la base de datos regresará a un estado consistente cuando se complete la transacción.

Es importante señalar que, aunque las transacciones proporcionan consistencia genérica de base de datos al asegurar que los cambios a los datos solo se tornarán permanentes después de que una transacción haya sido confirmada como exitosa, depende del usuario o de la aplicación garantizar que la secuencia de operaciones SQL efectuadas dentro de cada transacción dé siempre como resultado una base de datos consistente.

Efectos de las operaciones COMMIT y ROLLBACK

Como se señaló, las transacciones normalmente son terminadas al ejecutar los enunciados SQL COMMIT o ROLLBACK . Para entender cómo funcionan cada uno de estos comandos, es útil observar un ejemplo.

Si los siguientes enunciados SQL están en el orden mostrado:

Listado 1. Carga de trabajo simple consistente en tres transacciones
	  CONNECT TO MY_DB
	  CREATE TABLE DEPARTMENT (DEPT_ID INTEGER NOT NULL, DEPT_NAME VARCHAR(20))
	  INSERT INTO DEPARTMENT VALUES(100, 'PAYROLL')
	  INSERT INTO DEPARTMENT VALUES(200, 'ACCOUNTING')
	  COMMIT    
	    
	  INSERT INTO DEPARTMENT VALUES(300, 'SALES')
	  ROLLBACK  
	    
	  INSERT INTO DEPARTMENT VALUES(500, 'MARKETING')
	  COMMIT

Una tabla llamada DEPARTMENT será creada, que se verá de forma similar a la siguiente:

DEPT_ID DEPT_NAME
100 PAYROLL
200 ACCOUNTING
500 MARKETING

Esto es porque cuando se ejecuta el primer enunciado COMMIT , la creación de la tabla llamada DEPARTMENT, junto con la inserción de los dos registros en la tabla DEPARTMENT, serán permanentes. Por otro lado, cuando se ejecuta el primer enunciado ROLLBACK , el tercer registro insertado en la tabla DEPARTMENT es removido y la tabla es retornada al estado en el que estaba antes de que se efectuara la operación de inserción. Finalmente, cuando se ejecuta el segundo enunciado COMMIT , la inserción del cuarto registro en DEPARTMENT se torna permanente y la base de datos regresa de nuevo a un estado consistente.

Como puede ver en este ejemplo, una operación de confirmación o de retroacción solo afecta cambios que se hayan efectuado dentro de la transacción que sean terminados por la operación de confirmación o de retroacción. Mientras que los cambios permanezcan sin confirmar, otros usuarios o aplicaciones normalmente no pueden verlos (existen excepciones, las cuales veremos luego), y se pueden revertir efectuando simplemente una operación de retroacción. No obstante, una vez que los datos han sido confirmados, estos quedan disponibles para otros usuarios y aplicaciones y ya no podrán ser revertidos por una aplicación de retroacción.

Efectos de una transacción no exitosa

Acabamos de ver lo que sucede cuando una transacción es terminada por un enunciado COMMIT o ROLLBACK . ¿Pero qué sucede si se presenta una falla de sistema antes de que se complete la transacción? En este caso, el DB2 Database Manager revertirá todos los cambios no confirmados para restaurar la consistencia de base de datos que presume que existía cuando se inició la transacción. La Figura 1 compara los efectos de una transacción exitosa con los de una transacción que falla antes de que se pueda terminar de forma exitosa.

Figura 1. Comparando transacciones exitosas y no exitosas
Comparando transacciones exitosas y no exitosas

Niveles de concurrencia y de aislamiento

Se puede presentar el fenómeno en el que múltiples usuarios acceden a una base de datos

En entornos de usuario individual, cada transacción se ejecuta de manera serial y no encuentra interferencia de otras transacciones. Sin embargo, en entornos multi-usuario, las transacciones pueden (y lo hacen con frecuencia) ejecutarse de forma simultánea. Como resultado, cada transacción tiene el potencial para interferir con otras transacciones activas. Las transacciones que tienen el potencial de interferir entre sí son llamadas transacciones intercaladas o paralelas , mientras que las transacciones que se ejecutan de forma aislada de otras son conocidas como serializables, lo que significa que los resultados de ejecutarlas simultáneamente no serán diferentes a los resultados de ejecutarlas una después de otra (serialmente). Cuando se utilizan transacciones paralelas en entornos multi-usuario, pueden ocurrir cuatro tipos de fenómenos:

  • Actualización perdida: Esto ocurre cuando dos transacciones leen y luego intentan actualizar los mismos datos, y una de las actualizaciones se pierde. Por ejemplo: la Transacción 1 y la Transacción 2 leen la misma fila de datos y ambas calculan nuevos valores para esa fila, con base en los datos leídos. Si la Transacción 1 actualiza la fila con su nuevo valor y la Transacción 2 actualiza la misma fila, la operación de actualización efectuada por la Transacción 1 se pierde. Gracias a la forma en que está diseñado, DB2 for Linux, UNIX y Windows no permite que ocurra este tipo de fenómeno.

  • Lectura sucia: Esto ocurre cuando una transacción lee datos que todavía no han sido confirmados. Por ejemplo: la Transacción 1 cambia una fila de datos y la Transacción 2 lee la fila cambia da antes de que la Transacción 1 haya confirmado el cambio. Si la Transacción 1 revierte el cambio, la Transacción 2 habrá leído datos que se considera que nunca existieron.

  • Lectura no repetible: Esto ocurre cuando una transacción lee la misma fila de datos dos veces, pero obtiene diferentes valores cada vez. Por ejemplo: la Transacción 1 lee una fila de datos y la Transacción 2 cambia o elimina esa fila y confirma el cambio. Cuando la Transacción 1 intenta volver a leer la fila, recuperará diferentes valores de datos (si la fila fue actualizada) o descubrirá que la fila ya no existe (si la fila fue eliminada).

  • Fantasma: Esto ocurre cuando una fila de datos que coincide con los criterios de búsqueda no se ve inicialmente, pero luego se ve en una operación de lectura posterior. Por ejemplo: la Transacción 1 lee un conjunto de filas que satisfacen algunos criterios de búsqueda y la Transacción 2 inserta una nueva fila que coincide con los criterios de búsqueda de la Transacción 1. Si la Transacción 1 vuelve a ejecutar la consulta que produjo el conjunto original de filas, se recuperará un conjunto de filas diferente.

Mantener la consistencia y la integridad de una base de datos, mientras se permite que más de una aplicación acceda a los mismos datos, al mismo tiempo, se conoce como concurrencia. Una de las formas mediante las cuales DB2 for Linux, UNIX y Windows intenta imponer la concurrencia es mediante el uso de niveles de aislamiento, los cuales determinan cómo se bloquean o aíslan los datos usados en una transacción, de otras transacciones, mientras la primera transacción trabaja con ellos. DB2 for Linux, UNIX y Windows usa los siguientes niveles de aislamiento para imponer la concurrencia:

  • Lectura repetible
  • Estabilidad de lectura
  • Estabilidad de cursor
  • Lectura no confirmada

El nivel de aislamiento de lectura evita todos los fenómenos, pero reduce significativamente el nivel de concurrencia (el número de transacciones que pueden acceder simultáneamente al mismo recurso) disponible. El nivel de aislamiento de lectura no confirmada proporciona el mayor nivel de concurrencia, pero permite que ocurran los tres fenómenos.

El nivel de aislamiento de Lectura Repetible

El nivel de aislamiento de lectura repetible es el nivel de aislamiento más restrictivo disponible. Cuando se usa, los efectos de una transacción se aíslan completamente de los efectos de otras transacciones concurrentes; las lecturas sucias, las lecturas no repetibles y los fantasmas no pueden ocurrir. Con la lectura repetible, cada fila que es referenciada de cualquier manera por la transacción que la posee, es bloqueada por el tiempo que dure esa transacción. Como resultado, si el mismo enunciado SELECT es emitido dos o más veces dentro de la misma transacción, el conjunto de resultados producidos siempre será el mismo. Además, las transacciones que se ejecutan bajo este nivel de aislamiento pueden recuperar el mismo conjunto de filas múltiples veces y efectuar cualquier número de operaciones sobre ellas hasta que se terminen, mediante operaciones de confirmación o de retroacción. No obstante, otras transacciones tienen prohibido efectuar operaciones para insertar, eliminar o actualizar que pudieran afectar cualquier fila a la que haya accedido la transacción que la posee, mientras esta operación permanezca activa. Para garantizar esta conducta, cada fila referenciada por la transacción que la posee estará bloqueada (no solo las filas que están siendo efectivamente recuperadas o modificadas). Así, si una transacción escanea 1.000 filas con el fin de recuperar 10, se adquieren y mantienen bloqueos sobre las 1.000 filas escaneadas, en lugar de solo las 10 recuperadas.

¿Cómo funciona el nivel de aislamiento de lectura repetible en una situación del mundo real? Suponga que usted usa una base de datos DB2 para mantener un seguimiento de los registros de un hotel, que consisten en información sobre reservación y precio de habitación, y usted tiene una aplicación basada en web que permite que las personas reserven habitaciones bajo una dinámica tipo primero en llegar, primero en ser atendido. Si su aplicación de reservaciones se ejecuta bajo un nivel de aislamiento de lectura repetible, un cliente que escanee la base de datos para un rango de fechas dado, puede prevenir que usted (el gestor) cambie el precio de habitación de cualquiera de las habitaciones a las que se accedió cuando se resolvía la consulta del cliente. De forma similar, otros clientes no podrán hacer ni cancelar reservaciones que pudieran hacer que cambiara la lista de habitaciones disponibles para el primer cliente si la misma consulta se ejecutara de nuevo (mientras la transacción del primer cliente permaneciera activa). No obstante, a usted se le permitiría cambiar los precios de las habitaciones de cualquier registro de habitación que no hubiera sido leído cuando se produjo la lista del primer cliente. De forma similar, otros clientes pueden hacer o cancelar reservaciones de hotel de cualquier habitación cuyo registro no haya sido leído para producir una respuesta a la consulta del primer cliente. Esta conducta se ilustra en la Figura 2.

Figura 2. Ejemplo de un nivel de aislamiento de Lectura Repetible
Ejemplo de un nivel de aislamiento de Lectura Repetible

El nivel de aislamiento de Lectura de Estabilidad

El nivel de aislamiento de lectura de estabilidad no es tan restrictivo como el nivel de lectura repetible; por lo tanto, no aísla completamente una transacción de los efectos de otras transacciones concurrentes. El nivel de aislamiento de lectura de estabilidad evita lecturas sucias y lecturas no repetibles; no obstante, pueden presentarse fantasmas. Cuando se usa este nivel de aislamiento, solo se bloquean las filas que están siendo recuperadas o modificadas efectivamente por la transacción que las posee. Así, si una transacción escanea 1.000 filas con el fin de recuperar 10, solo se adquieren y mantienen bloqueos sobre las 10 filas recuperadas, no sobre las 1,000 escaneadas. Como resultado, si el mismo enunciado SELECT es emitido dos o tres veces dentro de la misma transacción, el conjunto de datos resultante producido puede no ser el mismo todas las veces.

Así como con el nivel de aislamiento de lectura repetible, las transacciones que se ejecutan bajo el nivel de aislamiento de lectura de estabilidad pueden recuperar un conjunto de filas y efectuar cualquier número de operaciones sobre ellas hasta que se terminen. Otras transacciones tienen prohibido efectuar operaciones de actualización o eliminación que afectarían el conjunto de filas recuperadas por la transacción que las posee, mientras la transacción exista; no obstante, otras transacciones pueden efectuar operaciones de inserción. Si las filas insertadas coinciden con los criterios de selección de una consulta emitida por la transacción que las posee, estas filas pueden aparecer como fantasmas en conjuntos de datos de resultados subsiguientes. Los cambios hechos a otras filas por otras transacciones no se verán hasta que hayan sido confirmados.

Entonces, ¿cómo cambia el nivel de aislamiento de lectura de estabilidad la forma en que funciona la aplicación de reservas de nuestro hotel? Cuando un cliente escanea la base de datos para obtener una lista de las habitaciones disponibles para un rango de fechas dado, usted podrá cambiar el precio de cualquiera de las habitaciones que no aparezca en la lista del cliente. De forma similar, otros clientes podrán hacer o cancelar reservaciones que pudieran hacer que cambiara la lista de habitaciones disponibles para el primer cliente si la misma consulta se ejecutara de nuevo. Si el primer cliente consulta la base de datos en busca de habitaciones disponibles para el mismo rango de fechas, la lista producida podría contener nuevas tasas de habitación y/o habitaciones que no estuvieran disponibles la primera vez que se generó la lista. Este comportamiento se ilustra en la Figura 3.

Figura 3. Ejemplo de nivel de aislamiento de Estabilidad de Lectura
Ejemplo de nivel de aislamiento de Estabilidad de Lectura

El nivel de aislamiento de Estabilidad de Cursor

El nivel de aislamiento de estabilidad de cursor es bastante relajado en la forma en que aísla los efectos de una restricción de los efectos de otras transacciones recurrentes. Este evita las lecturas sucias; no obstante, pueden presentarse lecturas no repetibles y fantasmas. Esto es porque en la mayoría de los casos, el nivel de aislamiento de estabilidad de cursor solo bloquea la fila que es referenciada actualmente por un cursor que fue declarado abierto por la transacción que lo posee.

Cuando una transacción que utiliza el nivel de aislamiento de estabilidad de cursor recupera una fila de una tabla mediante un cursor, ninguna otra transacción puede actualizar ni eliminar la fila mientras el cursor esté posicionado en ella. No obstante, otras transacciones pueden añadir nuevas filas a la tabla, así como efectuar operaciones de actualización o eliminación sobre filas posicionadas a cada lado de la fila bloqueada (siempre y cuando a la fila bloqueada no se haya accedido usando un índice). Una vez adquirido, el bloqueo permanece en efecto hasta que el cursor es reposicionado o hasta que la transacción que la posee se termine. (Si el cursor es reposicionado, el bloqueo que se mantiene sobre la lectura de fila anterior es liberado y se adquiere un nuevo bloqueo para la fila en la que el cursor está posicionado ahora). Además, si la transacción actual modifica cualquier fila que recupera, ninguna otra transacción tiene permitido actualizar ni eliminar esa fila sino hasta que se termine la transacción que la posee, incluso aunque el cursor pueda ya no estar posicionado en la fila modificada. Así como con los niveles de aislamiento de lectura repetible y de aislamiento de estabilidad, las transacciones que usan el nivel de aislamiento de estabilidad de cursor (que es el nivel de aislamiento predeterminado) no verán los cambios hechos a otras filas por otras transacciones no se verán hasta que hayan sido confirmados.

Si nuestra reservación de hotel se está ejecutando bajo el nivel de aislamiento de estabilidad de cursor, así es como funcionará. Cuando un cliente escanee la base de datos para obtener una lista de las habitaciones disponibles para un rango de fechas dado y luego ve la información sobre cada habitación en la lista producida, una habitación a la vez, usted podrá cambiar el precio de cualquiera de las habitaciones del hotel excepto el de la habitación que el cliente esté viendo actualmente (para el rango de fechas especificado). De forma similar, otros clientes podrán hacer o cancelar reservaciones de cualquier habitación del hotel excepto para la habitación que el cliente esté viendo actualmente (para el rango de fechas especificado). No obstante, ni usted ni otros clientes podrán hacer nada en el registro de la habitación que el primer cliente esté observando actualmente. Cuando el primer cliente vea información sobre otra habitación de la lista, usted y otros clientes podrán modificar el registro de la habitación que el primer cliente estaba observando (siempre y cuando el cliente no la haya reservado); sin embargo, nadie podrá cambiar el registro de la habitación que el cliente está observando ahora. Esta conducta se ilustra en la Figura 4.

Figura 4. Ejemplo del nivel de aislamiento de Estabilidad de Cursor
Ejemplo del nivel de aislamiento de Estabilidad de Cursor

El nivel de aislamiento de Lectura No Confirmada

El nivel de aislamiento de lectura no confirmada es el menos restrictivo de los niveles de aislamiento disponibles. De hecho, cuando se usa este nivel de aislamiento las filas recuperadas por una transacción solo son bloqueadas si otra transacción intenta eliminar o alterar la tabla de la cual se recuperaron las filas. Como las filas normalmente permanecen desbloqueadas cuando se usa este nivel de aislamiento, pueden ocurrir lecturas sucias, lecturas no repetibles y fantasmas. Por lo tanto, el nivel de aislamiento de lectura no comprometida se usa normalmente para transacciones que acceden a tablas y vistas de solo lectura , y para transacciones que ejecuten enunciados SELECT para los cuales los datos no confirmados de otras transacciones no tengan efectos adversos.

Como su nombre lo indica, las transacciones que se ejecutan bajo el nivel de aislamiento no confirmado pueden ver los cambios hechos a las filas por otras transacciones, antes de que esos cambios se confirmen. No obstante, tales transacciones no pueden ver las tablas de acceso ni las vistas, ni los índices que son creados por otras transacciones sino hasta que esas transacciones hayan sido confirmadas. Lo mismo se aplica para las tablas, vistas o índices existentes que se hayan eliminado; las transacciones que usan la lectura no confirmada solo sabrán que esos objetos ya no existen cuando se confirme la transacción que los eliminó. (Es importante señalar que cuando una transacción que se está ejecutando bajo este nivel de aislamiento usa un cursor actualizable, la transacción se comportará como si se estuviera ejecutando bajo el nivel de aislamiento de estabilidad de cursor, y aplicarán las restricciones del nivel de aislamiento de estabilidad de cursor).

Entonces, ¿cómo afectaría el nivel de aislamiento de lectura no confirmada nuestra aplicación de reservas de hotel? Ahora, cuando un cliente escanee la base de datos para obtener una lista de las habitaciones disponibles para un rango de fechas dado, usted podrá cambiar el precio de cualquiera de las habitaciones y en cualquier rango de fechas. De forma similar, otros clientes podrán hacer o cancelar reservaciones de cualquier habitación del hotel, incluyendo la habitación que el cliente está observando actualmente (por el rango de fecha especificado). Además, la lista de habitaciones producida por el primer cliente puede contener registros de habitaciones que otros clientes estén en proceso de reservar y que en realidad no estén disponibles. Este comportamiento se ilustra en la Figura 5.

Figura 5. Ejemplo de un nivel de aislamiento de Lectura No Confirmada
Ejemplo de un nivel de aislamiento de Lectura No Confirmada

Seleccionando el nivel de aislamiento adecuado

El nivel de aislamiento usado puede influenciar qué tan bien soporta la concurrencia la base de datos, y qué tan bien se desempeñan las aplicaciones concurrentes. Normalmente, entre más restrictivo es el nivel usado, menor concurrencia es posible y el desempeño de algunas aplicaciones puede degradarse mientras esperan que se liberen los bloqueos sobre algunos recursos. Así que ¿cómo decide usted qué nivel de aislamiento usar? La mejor forma es identificar cuáles tipos de fenómenos son inaceptables y luego seleccionar un nivel de aislamiento que evite que ocurran esos fenómenos:

  • Use el nivel de aislamiento de lectura repetible si está ejecutando consultas extensas y si no desea que transacciones concurrentes puedan hacer cambios que puedan causar que la consulta retorne diferentes resultados si se ejecuta más de una vez.

  • Lea el nivel de aislamiento de estabilidad de lectura cuando desee algún nivel de concurrencia entre aplicaciones, pero si también desea que filas calificadas permanezcan estables por el tiempo que dure una transacción individual.

  • Use el nivel de aislamiento de estabilidad de cursor cuando desee la máxima concurrencia entre aplicaciones pero si al mismo tiempo no desea que las consultas vean datos no confirmados.

  • Use el nivel de aislamiento de lectura no confirmada si está ejecutando consultas sobre tablas/vistas/bases de datos de solo lectura, o si no es importante si una consulta retorna valores de datos no confirmados.

Especificando el nivel de aislamiento a utilizar

Aunque los niveles de aislamiento controlan el comportamiento a nivel de transacción, en realidad estos se establecen a nivel de aplicación:

  • Para aplicaciones SQL incorporadas, el nivel de aislamiento se especifica al momento de la pre-compilación o cuando la aplicación esté vinculada a una base de datos (si se utiliza vinculación diferida). En este caso, el nivel de aislamiento se establece usando la opción ISOLATION del comando PRECOMPILE o BIND .

  • Para aplicaciones Open Database Connectivity (ODBC) y Call Level Interface (CLI), el nivel de aislamiento se establece en el momento de ejecución de aplicación, llamando la función SQLSetConnectAttr() con el atributo de conexión SQL_ATTR_TXN_ISOLATION especificado. (Alternativamente, el nivel de aislamiento para aplicaciones ODBC/CLI puede establecerse asignando u valora la palabra clave TXNISOLATION en el archivo de configuración db2cli.ini ; no obstante, este enfoque no proporciona la misma flexibilidad para cambiar niveles de aislamiento para diferentes transacciones dentro de una misma aplicación, que la que proporciona el primer enfoque).

  • Para aplicaciones Java Database Connectivity (JDBC) y SQLJ, el nivel de aislamiento se establece en el tiempo de ejecución de aplicación llamando al método setTransactionIsolation() que reside en la interfaz de conexión java.sql para DB2 for Linux, UNIX y Windows.

Cuando el nivel de aislamiento para una aplicación no está configurado explícitamente usando alguno de estos métodos, el nivel de aislamiento de estabilidad de cursor se usa de forma predeterminada. Este predeterminado se aplica para comandos DB2, enunciados SQL y scripts ejecutados desde el Command Line Processor (CLP), así como para aplicaciones SQL, ODBC/CLI, JDBC y SQLJ incorporadas. Por lo tanto, también es posible especificar el nivel de aislamiento para operaciones que serán llevadas a cabo desde el DB2 Command Line Processor (así como para los scripts que se pasarán al DB2 CLP para procesamiento). En este caso, el nivel de aislamiento se establece ejecutando el comando CHANGE ISOLATION antes de que se establezca una conexión a una base de datos.

Con DB2 for Linux, UNIX y Windows, la capacidad para especificar el nivel de aislamiento bajo el cual se va a ejecutar una consulta particular se suministró en forma de la cláusula WITH [RR | RS | CS | UR] que puede añadirse a un enunciado SQL SELECT . Un enunciado SELECT simple que usa esta cláusula se ve algo similar a este:

SELECT * FROM EMPLOYEE WHERE EMPID = '001' WITH RR

Si usted tiene una aplicación que necesite ejecutarse en un nivel de aislamiento menos restrictivo la mayoría del tiempo (para soportar una concurrencia máxima), pero que contenga algunas consultas para las cuales usted no debe permitir ningún fenómeno, esta cláusula proporciona un método excelente que se puede usar para lograr su objetivo.


Bloqueos

Cómo funcionan los bloqueos

En la sección sobre Niveles de concurrencia y de aislamiento, vimos que el DB2 for Linux, UNIX y Windows aísla las transacciones entre sí mediante el uso de bloqueos. Un bloqueo es un mecanismo que se utiliza para asociar un recurso de datos con una transacción única, con el propósito de controlar la forma en que otras transacciones interactúan con ese recurso mientras este está asociado con la transacción que le pertenece. (Se dice que la transacción que tiene un recurso bloqueado asociado mantiene o posee el bloqueo). El Database Manager DB2 usa bloqueos para evitar que las transacciones accedan a datos no confirmados escritos por otras transacciones (a menos que se use el nivel de aislamiento de Lectura No Confirmada) y para prohibir la actualización de filas por parte de otras transacciones cuando la transacción que los posee está usando un nivel de aislamiento restrictivo. Una vez se adquiere un bloqueo, este se mantiene hasta que se termine la transacción que lo posee; en ese punto, el bloqueo es liberado y el recurso de datos es puesto a disposición para otras transacciones.

Si una transacción intenta acceder a recursos de datos de una forma que sea incompatible con el bloqueo que está siendo mantenido por otra transacción (pronto veremos la compatibilidad de bloqueo), esa transacción debe esperar hasta que termine la transacción que lo posee. Esto se conoce como un evento de espera de bloqueo . Cuando ocurre un evento de espera de bloqueo, la transacción que está intentando acceder al recurso de datos simplemente detiene su ejecución hasta que la transacción haya terminado y se libere el bloqueo incompatible.

Atributos de bloqueo

Todos los bloqueos tienen los siguientes atributos básicos:

  • Objeto: El atributo de objeto identifica el recurso de datos que está siendo bloqueado. El DB2 Database Manager adquiere bloqueos sobre recursos de datos, como espacios de tabla, tablas y filas, cuando se necesiten.

  • Tamaño: El atributo de tamaño especifica el tamaño físico de la porción de recursos de datos que están siendo bloqueados. Un bloqueo no siempre tiene que controlar todo un recurso de datos. Por ejemplo, en lugar de darle a una aplicación control exclusivo sobre toda una tabla, el DB2 Database Manager puede darle a una aplicación control exclusivo sobre una fila específica de una tabla.

  • Duración: El atributo de duración especifica el tiempo durante el cual se mantendrá un bloqueo. Normalmente el nivel de aislamiento de la transacción es el que controla la duración de un bloqueo.

  • Modo: El atributo de modo especifica el tipo de acceso permitido al propietario del bloqueo, así como el tipo de acceso permitido a los usuarios concurrentes al recurso de datos bloqueado. A este atributo comúnmente se le conoce como el estado de bloqueo.

Estados de bloqueo

El estado de bloqueo determina el tipo de acceso permitido al propietario del bloqueo, así como el tipo de acceso permitido a los usuarios concurrentes al recurso de datos bloqueado. La Tabla 1 identifica los estados de bloqueo que están disponibles, para aumentar el control.

Tabla 1. Estados de bloqueo
Estado de bloqueo (Modo)Objetos aplicablesDescripción
Intent None (IN)Espacios de tabla y tablasEl poseedor del bloqueo puede leer datos de la tabla bloqueada, incluyendo datos no confirmados, pero no puede cambiar estos datos. En este modo, el poseedor del bloqueo no adquiere bloqueos de nivel de fila; por lo tanto, otras aplicaciones concurrentes pueden leer y cambiar datos de la tabla.
Intent Share (IS)Espacios de tabla y tablasEl poseedor del bloqueo puede leer datos de la tabla bloqueada, pero no puede cambiar estos datos. De nuevo, como el poseedor del bloqueo no adquiere bloqueos de nivel de fila, otras aplicaciones concurrentes pueden leer y cambiar datos de la tabla. (Cuando una transacción posee un bloqueo Intent Share sobre una tabla, esta adquiere un bloqueo Share sobre cada fila que lea). Este bloqueo es adquirido cuando una transacción no transmite la intención de actualizar filas de la tabla. (Los enunciados SELECT FOR UPDATE, UPDATE ... WHERE y INSERT transmiten la intención de actualizar).
Next Key Share (NS)FilasEl poseedor del bloqueo y todas las transacciones concurrentes pueden leer los datos de la fila bloqueada, pero no pueden cambiarlos. Este bloqueo es adquirido en lugar de un bloqueo Share sobre datos que sean leídos usando niveles de aislamiento de Estabilidad de Lectura o de Estabilidad de Cursor.
Share (S)Tablas y filasEl poseedor del bloqueo y cualquier otra transacción concurrente pueden leer los datos de la tabla o fila bloqueada, pero no pueden cambiarlos. Mientras la tabla no esté en bloqueo Share, las filas individuales de esa tabla pueden tener bloqueo Share. No obstante, si una tabla tiene bloqueo Share, los bloqueos Share de nivel de fila de esa tabla no pueden ser adquiridos por el propietario del bloqueo. Si una tabla o una fila tienen bloqueo Share, otras transacciones concurrentes pueden leer los datos, pero no pueden cambiarlos.
Intent Exclusive (IX)Espacios de tabla y tablasEl poseedor del bloqueo y cualquier otra aplicación concurrente pueden leer y cambiar los datos de la tabla bloqueada. Cuando el poseedor del bloqueo lee de la tabla, este adquiere un bloqueo Share sobre cada fila que lee y adquiere un bloqueo Update y un bloqueo Exclusive sobre cada fila que actualiza. Otras aplicaciones concurrentes pueden leer y actualizar la tabla bloqueada. Este bloqueo es adquirido cuando una transacción transmite la intención de actualizar filas de la tabla.
Share With Intent Exclusive (SIX)TablasEl poseedor del bloqueo puede leer y cambiar los datos de la tabla bloqueada. El poseedor del bloqueo adquiere bloqueos Exclusive sobre las filas que actualiza, pero no adquiere bloqueos sobre filas que lea; por lo tanto, otras aplicaciones concurrentes pueden leer pero no actualizar los datos de la tabla bloqueada.
Update (U)Tablas y filasEl poseedor del bloqueo puede actualizar datos de la tabla bloqueada y el poseedor del bloqueo automáticamente adquiere bloqueos Exclusive sobre cualquier fila que actualice. Otras aplicaciones concurrentes pueden leer pero no actualizar los datos de la tabla bloqueada.
Next Key Weak Exclusive (NW)FilasEl poseedor del bloqueo puede leer pero no puede cambiar la fila bloqueada. Este bloqueo se adquiere en la siguiente fila de una tabla cuando se inserta una fila en el índice de una tabla que no sea catalogada.
Exclusive (X)Tablas y filasEl poseedor del bloqueo puede leer y cambiar los datos de la tabla o fila bloqueada. Si se adquiere un bloqueo Exclusive, solo las aplicaciones que usan el nivel de aislamiento de Lectura No Confirmada tienen permitido el acceso a la tabla o fila(s) bloqueada(s). Los bloqueos exclusivos son adquiridos por recursos de datos que van a ser manipulados con los enunciados INSERT, UPDATE, y/o DELETE .
Weak Exclusive (W)FilasEl poseedor del bloqueo puede leer y cambiar la fila bloqueada. Este bloqueo se adquiere sobre una fila cuando se inserta en una tabla que no sea catalogada.
Super Exclusive (Z)Espacios de tabla y tablasEl poseedor del bloqueo puede alterar una tabla, eliminar una tabla, crear un índice o eliminar un índice. Este bloqueo se adquiere automáticamente sobre una tabla siempre que una transacción intente efectuar cualquiera de estas operaciones. No se permite a ninguna otra transacción concurrente leer ni actualizar la tabla sino hasta que este bloqueo haya sido removido.

Cómo se adquieren los bloqueos

En la mayoría de los casos, el DB2 Database Manager adquiere bloqueos de forma implícita a medida que se necesitan, y estos bloqueos permanecen bajo el control del DB2 Database Manager. Excepto en situaciones donde se use nivel de aislamiento de Lectura No Confirmada, una transacción nunca necesita solicitar un bloqueo de forma explícita. De hecho, el único objeto de base de datos que puede ser bloqueado explícitamente por una transacción es una tabla. La Figura 6 ilustra la lógica que se usa para determinar qué tipo de bloqueo adquirir para un objeto referenciado.

Figura 6. Cómo se adquieren los bloqueos
Cómo se adquieren los bloqueos

El DB2 Database Manager siempre intenta adquirir bloqueos de nivel de fila. No obstante, este comportamiento puede ser modificado al ejecutar una forma especial del enunciado ALTER TABLE , como sigue:

ALTER TABLE [ TableName ] LOCKSIZE TABLE

donde TableName identifica el nombre de una tabla existente para la cual todas las transacciones deben adquirir bloqueos de nivel de tabla para cuando se acceda a ellos.

El DB2 Database Manager también puede forzarse para que adquiera un bloqueo de nivel de tabla sobre una tabla para una transacción específica, ejecutando el enunciado LOCK TABLE , como sigue:

LOCK TABLE [ TableName ] IN [SHARE | EXCLUSIVE] MODE

donde TableName identifica el nombre de una tabla existente para la cual se va a adquirir un bloqueo de nivel de tabla (siempre y cuando ninguna otra transacción tenga un bloqueo incompatible sobre esta tabla). Si este enunciado es ejecutado con el modo SHARE especificado, se adquirirá un bloqueo de nivel de tabla que permitirá que otras transacciones lean los datos almacenados en ella, pero no cambiarlos; si se ejecuta con el modo EXCLUSIVE especificado, se adquirirá un bloqueo de nivel de tabla que no permitirá que otras transacciones lean ni modifiquen los datos almacenados en ella.


Bloqueos y desempeño

Compatibilidad de bloqueo

Si el estado de un bloqueo ubicado sobre un recurso de datos permite que otro bloqueo sea ubicado sobre el mismo recurso, se dice que los dos bloqueos (o estados) son compatibles. Siempre que una transacción mantenga un bloqueo sobre un recurso de datos y una segunda transacción solicite un bloqueo sobre el mismo recurso, el DB2 Database Manager examina los dos estados de bloqueo para determinar si son compatibles o no. Si los bloqueos son compatibles, el bloqueo es concedido a la segunda transacción (siempre y cuando no hayan más transacciones esperando por el recurso de datos). Si, no obstante, los bloqueos son incompatibles, la segunda transacción debe esperar hasta que la primera transacción libere su bloqueo antes de que pueda lograr acceso al recurso y continuar el procesamiento. (Si hay más de un bloqueo incompatible establecido, la segunda transacción debe esperar hasta que se liberen todos los bloqueos). Consulte la documentación IBM DB2 for Linux, UNIX, and Windows Administration Guide: Performance (o busque en el DB2 Information Center temas de Compatibilidad de tipos de bloqueo ), información específica sobre cuáles bloqueos son compatibles con cuáles otros y cuáles no.

Conversión de bloqueos

Cuando una transacción intenta acceder a recursos de datos sobre los que ya opere un bloqueo, y el modo de acceso necesario requiera un bloqueo más restrictivo que el que ya está aplicado, el estado del bloqueo aplicado cambia al estado más restrictivo. La operación de cambiar el estado de un bloqueo que ya está siendo aplicado, hacia un estado más restrictivo se conoce como conversión de bloqueo. Las conversiones de bloqueo ocurren porque una transacción solo puede mantener un bloqueo sobre un recurso de datos a la vez.

En la mayoría de los casos, la conversión de bloqueo es llevada a cabo para bloqueos de nivel de fila y el proceso de conversión es bastante sencillo. Por ejemplo, si se mantiene un bloqueo de nivel de fila Share (S) o uno Update (U) y se necesita un bloqueo Exclusive (X), el bloqueo mantenido se convertirá a bloqueo Exclusive (X). Sin embargo, los bloqueos Intent Exclusive (IX) y Share (S) son casos espaciales dado que ninguno se considera más restrictivo que el otro. Así, si alguno de estos bloqueos de nivel de fila es mantenido y se solicita el otro, el bloqueo mantenido se convierte a un Share con bloqueo Intent Exclusive (SIX). Conversiones similares resultan en el estado de bloqueo solicitado, convirtiéndose en el nuevo estado de bloqueo del bloqueo mantenido, siempre que el estado de bloqueo solicitado sea más restrictivo. (La conversión de bloqueo solo ocurre si un bloqueo mantenido puede incrementar se restricción). En cuanto un estado de bloqueo ha sido convertido, el bloqueo permanece en su estado más alto obtenido hasta que la transacción que mantiene el bloqueo se termina.

Escalamiento de bloqueo

Todos los bloqueos requieren espacio para almacenamiento; dado que el espacio disponible para almacenamiento no es infinito, el DB2 Database Manager debe limitar la cantidad de espacio que se puede usar para los bloqueos (esto se hace mediante el parámetro maxlocks de configuración de base de datos). Para evitar que un agente específico de base de datos exceda las limitaciones de espacio de bloqueo establecidas, un proceso conocido como escalamiento de bloqueo se lleva a cabo automáticamente cada vez que se hayan adquirido demasiados bloqueos (de cualquier tipo). El escalamiento de bloqueos es la conversión de muchos bloqueos individuales de nivel de fila dentro de la misma tabla, en un solo bloqueo de nivel de tabla. Como el escalamiento de bloqueo es manejado internamente, el único resultado detectable externamente puede ser la reducción en el acceso concurrente de una o más tablas.

Así es como funciona el escalamiento de bloqueo: Cuando una transacción solicita un bloqueo y el espacio de almacenamiento de bloqueos está lleno, se selecciona una de las tablas asociadas con la transacción, se adquiere un bloqueo de nivel de tabla a su nombre, todos los bloqueos de nivel de fila son liberados (para crear espacio en la estructura de datos de la lista de bloqueo) y el bloqueo de nivel de tabla es añadido a la lista de bloqueo. Si este proceso no libera suficiente espacio, se selecciona otra tabla y el proceso se repite hasta que haya suficiente espacio libre. En este punto, el bloqueo solicitado es adquirido y la transacción reanuda su ejecución. No obstante, si el espacio de bloqueo necesario todavía no está disponible después de que se hayan escalado todos los bloqueos de nivel de fila de la transacción, se solicita a la transacción (mediante un código de error SQL) o que confirme o que revierta todos los cambios realizados desde su inicio y la transacción se termina.

Tiempos de espera de bloqueo excedidos

Siempre que una transacción mantiene un bloqueo sobre un recurso de datos en particular (por ejemplo, una tabla o una fila), se puede estar negando el acceso de otras transacciones al recurso hasta que la transacción que lo posee termine y libere todos los bloqueos que ha adquirido. Si no se cuenta con algún mecanismo de detección de tiempo de espera excedido de bloqueo, una transacción podría esperar indefinidamente a que un bloqueo se libere. Tal situación puede ocurrir, por ejemplo, cuando una transacción está esperando que un bloqueo mantenido por una aplicación de otro usuario sea liberado, y el otro usuario ha abandonado sus estación de trabajo sin llevar a cabo ninguna interacción que pudiera permitir que la aplicación terminara su propia transacción. Obviamente, tal situación puede causar un pobre desempeño de aplicación. Para evitar que otras aplicaciones se atasquen cuando esto suceda, se puede especificar un valor de tiempo de espera de bloqueo excedido, en el archivo de configuración de una base de datos (vía el parámetro locktimeout de configuración de base de datos). Cuando se utiliza, este valor controla la cantidad de tiempo que esperará cualquier transacción para obtener el bloqueo solicitado. Si un bloqueo deseado no es adquirido antes de que transcurra el intervalo de tiempo especificado, la aplicación que espera recibirá un error y la transacción que solicita el bloqueo será revertida. Los entornos de aplicaciones de transacciones distribuidas son particularmente propensos a estos tipos de situaciones; usted puede evitarlas usando tiempos de espera de bloqueo excedidos.

Puntos muertos

Aunque la situación de una transacción esperando indefinidamente para que se libere un bloqueo por parte de otra transacción se puede resolver estableciendo tiempos de espera de bloqueo excedidos, existe un escenario donde la contención de bloqueos por dos o más transacciones no puede ser resuelta por un tiempo de espera excedido. Esta situación es conocida como un punto muerto, o más específicamente, un ciclo de punto muerto. La mejor forma de ilustrar cómo puede ocurrir un punto muerto es mediante un ejemplo: Suponga que la Transacción 1 adquiere un bloqueo Exclusive (X) sobre la Tabla A y que la Transacción 2 adquiere un bloqueo Exclusive (X) sobre la Tabla B. Ahora, suponga que la Transacción 1 intenta adquirir un bloqueo Exclusive (X) sobre la Tabla B y que la Transacción 2 intenta adquirir un bloqueo Exclusive (X) sobre la Tabla A. El procesamiento de ambas transacciones se suspenderá hasta que su segunda solicitud de bloqueo se otorgue. Sin embargo, como ninguna de las solicitudes de bloqueo puede concederse hasta que alguna de las transacciones libere el bloqueo que mantiene actualmente (efectuando una operación de confirmación o retroacción) y porque ninguna transacción puede liberar el bloqueo que mantiene actualmente (porque ambas están suspendidas y esperando los bloqueos), las transacciones están bloqueadas en un ciclo de punto muerto. La Figura 7 ilustra este escenario de punto muerto.

Figura 7. Un ciclo de punto muerto
Un ciclo de punto muerto

Cuando ocurre un ciclo de punto muerto, cada transacción involucrada esperará indefinidamente a que se libere un bloqueo a menos que algún agente externo intervenga. Con el DB2 for Linux, UNIX y Windows, este agente es un proceso asíncrono de sistema y de segundo plano que se conoce como el detector de puntos muertos. La única responsabilidad del detector de puntos muertos es ubicar y resolver cualquier punto muerto que se encuentre en el sub-sistema de bloqueo. Cada base de datos tiene su propio detector de puntos muertos, el cual es activado como parte del proceso de inicialización de base de datos. Una vez activado, el detector de puntos muertos permanece "dormido" la mayor parte del tiempo, pero se "despierta" en intervalos pre-establecidos para examinar el subsistema de bloqueo en busca de ciclos de punto muerto. Si un detector de puntos muertos descubre que existe un ciclo de punto muertos, aleatoriamente selecciona una de las transacciones del ciclo para terminarla y revertirla. La transacción seleccionada recibe un código de error SQL y todos los bloqueos que haya adquirido son liberados; la(s) transacción(es) restantes pueden entonces proceder porque se ha roto el punto muerto.

Granularidad de bloqueo

Se mencionó anteriormente que siempre que una transacción mantiene un bloqueo sobre un recurso de datos en particular, se puede estar negando el acceso de otras transacciones al recurso hasta que la transacción que lo posee se termine. Por lo tanto, para optimizar para máxima concurrencia, los bloqueos de nivel de fila son usualmente mejores que los bloqueos de nivel de tabla porque estos limitan el acceso a un recurso mucho más pequeño. No obstante, como cada bloqueo adquirido requiere cierta cantidad de tiempo de procesamiento y de espacio de almacenamiento para ser adquirido y manejado, un bloqueo de nivel de tabla requerirá menos sobrecarga que muchos bloqueos individuales de nivel de fila. A menos que se especifique de otra forma, los bloqueos de nivel de fila son adquiridos predeterminadamente.

La granularidad de los bloqueos (Esto es, si se adquieren bloqueos de nivel de fila o bloqueos de nivel de tabla) pueden controlarse mediante el uso de los enunciados ALTER TABLE ... LOCKSIZE TABLE, ALTER TABLE ... LOCKSIZE ROW y LOCK TABLE . El enunciado ALTER TABLE ... LOCKSIZE TABLE proporciona un enfoque global a una granularidad que da como resultado bloqueos de nivel de tabla que son adquiridos por todas las transacciones que acceden a filas dentro de una tabla en particular. Por otro lado, el enunciado LOCK TABLE permite que se adquieran bloqueos de nivel de tabla a nivel de transacción individual. Cuando se usa cualquiera de estos enunciados, se adquiere un bloqueo individual de tabla, Share (S) o Exclusive (X), siempre que se necesite un bloqueo. Como resultado, el desempeño de bloqueo normalmente es mejorado, dado que se debe adquirir y liberar un bloqueo de nivel de tabla, en lugar de varios bloqueos diferentes de nivel de fila. Sin embargo, cuando se usa el bloqueo de nivel de tabla, la concurrencia puede verse reducida si las transacciones se largo término adquieren bloqueos de nivel de tabla Exclusive en lugar de Share.

Transacciones y bloqueo

Desde el punto de vista del bloqueo, todas las transacciones caen típicamente bajo una de las siguientes categorías:

  • Solo lectura: Esto se refiere a transacciones que contengan enunciados SELECT (los cuales son intrínsecamente de solo lectura), enunciados SELECT que tienen la cláusula FOR READ ONLY especificada, o enunciados SQL que son ambiguos, pero que se presume que son de solo lectura por la opción BLOCKING especificada como parte del proceso de pre-compilación y/o enlace.

  • Intención de cambio: Esto se refiere a transacciones que contienen enunciados SELECT que tengan la cláusula FOR UPDATE especificada, o enunciados SQL que son ambiguos, pero que se presume que tienen la intención de hacer cambios, por la forma en que son interpretados por el pre-compilador SQL.

  • Cambio: Esto se refiere a transacciones que contengan enunciados INSERT, UPDATE, y/o DELETE , pero no enunciados UPDATE ... WHERE CURRENT OF ... ni DELETE ... WHERE CURRENT OF ... .

  • Controlado por cursor: Esto se refiere a transacciones que contienen enunciados UPDATE ... WHERE CURRENT OF ... y DELETE ... WHERE CURRENT OF ... .

Solo lectura las transacciones normalmente usan bloqueos Intent Share (IS) y/o Share (S). Las transacciones con intención de cambio , por otro lado, usan bloqueos Update (U), Intent Exclusive (IX) y Exclusive (X) para tablas, y bloqueos Share (S), Update (U) y Exclusive (X). Las transacciones Change tienden a usar los bloqueos Intent Exclusive (IX) y/o Exclusive (X), mientras que las transacciones Controladas por cursor a menudo usan bloqueos Intent Exclusive (IX) y/o Exclusive (X).

Cuando se prepara un enunciado SQL para ejecución, el optimizador DB2 explora varias formas para satisfacer la solicitud de ese enunciado y estima el costo de ejecución involucrado para cada enfoque. Con base en esta evaluación, el optimizador DB2 selecciona luego lo que considera que es el plan de acceso óptimo. (El plan de acceso especifica las operaciones requeridas y el orden en que esas preparaciones se llevarán a cabo para resolver una solicitud SQL). Un plan de acceso puede usar una de dos formas de acceder a los datos de una tabla: leyendo directamente de la tabla (lo cual se conoce como efectuar una tabla o un escaneo de relación ), o leyendo un índice sobre esa tabla y luego recuperando la fila de la tabla a la que se refiere una entrada de índice en particular (lo cual se conoce como un escaneo de índice ).

La ruta de acceso seleccionada por el optimizador DB2, el cual es a menudo determinado por el diseño de la base de datos, puede tener un impacto significativo en el número de bloqueos adquiridos y en los estados de bloqueo usados. Por ejemplo, cuando un escaneo de índice es usado para ubicar una fila específica, el DB2 Database Manager muy probablemente adquirirá uno o más bloqueos Intent Share (IS) de nivel de fila. Sin embargo, se usa un escaneo de tabla porque toda la tabla debe ser escaneada, en secuencia, para localizar una fila específica, el DB2 Database Manager puede optar por adquirir un solo bloqueo Share (S) de nivel de tabla.


Resumen

Este tutorial estuvo diseñado para introducirle al concepto de consistencia de datos y a los diferentes mecanismos utilizados por DB2 for Linux, UNIX y Windows para mantener la consistencia de base de datos en entornos tanto individuales como multi-usuario. Una base de datos pueden tornarse inconsistente si algún usuario olvida realizar todos los cambios necesarios, si el sistema colapsa mientras el usuario está en la mitad de un cambio, o si una aplicación de base de datos se detiene por alguna razón. La inconsistencia también se puede presentar cuando varios usuarios/aplicaciones acceden a los mismos recursos de datos al mismo tiempo. Por ejemplo, un usuario puede leer los cambios de otro usuario antes de que todas las tablas hayan sido actualizadas apropiadamente y efectuar algunas acciones inapropiadas o hacer cambios incorrectos con base en los datos leídos prematuramente. En un esfuerzo para prevenir la inconsistencia de datos, particularmente en un entorno multi-usuario, los desarrolladores de DB2 for Linux, UNIX y Windows incorporaron en su diseño los siguientes mecanismos para soporte de consistencia de datos:

  • Transacciones
  • Niveles de aislamiento
  • Bloqueos

Una transacción (también conocida como una unidad de trabajo) es una secuencia recuperable de una o más operaciones SQL, agrupadas como una sola unidad, normalmente dentro de un proceso de aplicación. El inicio y terminación de una transacción definen los puntos de consistencia de una base de datos; o los efectos de todas las operaciones SQL efectuadas dentro de una transacción son aplicados (confirmados), o los efectos de todas las operaciones SQL efectuadas se deshacen completamente y se descartan (revertidos). En cualquier caso, se garantiza que la base de datos regresará a un estado consistente cuando se complete cada transacción.

Mantener la consistencia de una base de datos y la integridad de los datos, mientras se permite que más de una aplicación acceda a los mismos datos, al mismo tiempo, se conoce como concurrencia. Con DB2 for Linux, UNIX y Windows, la concurrencia de impone mediante el uso de niveles de aislamiento. Hay cuatro niveles de aislamiento disponibles:

  • Lectura repetible
  • Estabilidad de lectura
  • Estabilidad de cursor
  • Lectura no confirmada

El nivel de aislamiento de lectura evita todos los fenómenos, pero reduce significativamente el nivel de concurrencia (el número de transacciones que pueden acceder simultáneamente al mismo recurso) disponible. El nivel de aislamiento de lectura no confirmada proporciona el mayor nivel de concurrencia, pero permite que ocurran lecturas sucias, lecturas no repetibles y fantasmas.

Junto con los niveles de aislamiento, DB2 for Linux, UNIX y Windows proporciona concurrencia en entornos multi-usuario mediante el uso de bloqueos. Un bloqueo es un mecanismo que se utiliza para asociar un recurso de datos con una transacción única, con el propósito de controlar la forma en que otras transacciones interactúan con ese recurso mientras este está asociado con la transacción que posee el bloqueo. Hay varios tipos diferentes de bloqueo disponibles:

  • Intent None (IN)
  • Intent Share (IS)
  • Next Key Share (NS)
  • Share (S)
  • Intent Exclusive (IX)
  • Share with Intent Exclusive (SIX)
  • Update (U)
  • Next Key Weak Exclusive (NW)
  • Exclusive (X)
  • Weak Exclusive (W)
  • Super Exclusive (Z)

Para mantener la integridad de datos, el DB2 Database Manager adquiere bloqueos de forma implícita y todos los bloqueos adquiridos permanecen bajo el control del DB2 Database Manager. Los bloqueos se pueden ubicar en espacios de tabla, tablas y filas.

Para optimizar para máxima concurrencia, los bloqueos de nivel de fila son usualmente mejores que los bloqueos de nivel de tabla porque estos limitan el acceso a un recurso mucho más pequeño. No obstante, como cada bloqueo adquirido requiere cierta cantidad de espacio de almacenamiento y de tiempo de procesamiento para ser administrado, un bloqueo de nivel de tabla requerirá menos sobrecarga que muchos bloqueos individuales de nivel de fila.

Recursos

Aprender

Obtener los productos y tecnologías

  • Una versión de prueba del DB2 9 está disponible para descarga.
  • Descargue DB2 Express-C, una versión gratuita del DB2 Express Edition para la comunidad que ofrece los mismos recursos de datos principales que el DB2 Express Edition y proporciona una base sólida para construir e implementar aplicaciones.

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Information mgmt
ArticleID=793853
ArticleTitle=Preparación para el examen 730 Fundamentos DB2 9, Parte 6: Concurrencia de datos
publish-date=02162012