resultset(administracion base de datos)

29
UNIVERSIDAD TÉCNICA ESTATAL DE QUEVEDO FACULTAD DE CIENCIAS DE LA INGENIERÍA INGERNIERÍA EN SISTEMAS CONSULTA RESULTSET Nombre: Yanchaluiza Coello Héctor Bladimir Docente: Ing. Iván Jaramillo Unidad de Aprendizaje: Administración de base de datos

Upload: joselito-yanchaluiza

Post on 30-Jul-2015

377 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: RESULTSET(Administracion Base de Datos)

UNIVERSIDAD TÉCNICA ESTATAL DE QUEVEDOFACULTAD DE CIENCIAS DE LA INGENIERÍA

INGERNIERÍA EN SISTEMAS

CONSULTA RESULTSET

Nombre:

Yanchaluiza Coello Héctor Bladimir

Docente:

Ing. Iván Jaramillo

Unidad de Aprendizaje:

Administración de base de datos

2012 - 2013

Page 2: RESULTSET(Administracion Base de Datos)

RESULTSET

Una tabla de datos que representan un conjunto de resultados de base de datos, que normalmente se genera mediante la ejecución de una instrucción que consulta la base de datos.

Un ResultSet objeto mantiene un cursor que apunta a la fila de datos actual. Inicialmente, el cursor se coloca delante de la primera fila. El siguiente método mueve el cursor a la siguiente fila, y porque devuelve false cuando no hay más filas en el ResultSet objeto, que puede ser utilizado en un tiempo bucle para iterar a través del conjunto de resultados.

Un defecto ResultSet objeto no es actualizable y tiene un cursor que se mueve sólo hacia adelante. Por lo tanto, se puede iterar a través de una sola vez y sólo a partir de la primera fila a la última fila.

El ResultSet interfaz proporciona getter métodos (getBoolean, getLong, y así sucesivamente) para recuperar los valores de columna de la fila actual. Los valores se pueden recuperar mediante el número de índice de la columna o el nombre de la columna. En general, utilizando el índice de la columna será más eficiente. Las columnas se numeran del 1. Para obtener la máxima portabilidad, como resultado columnas del conjunto dentro de cada fila debe leerse de izquierda a derecha, y cada columna debe ser leída sólo una vez.

Para los métodos getter, un controlador JDBC intenta convertir los datos subyacentes al tipo Java especificado en el método getter y devuelve un valor adecuado Java. La especificación JDBC tiene una tabla que muestra las asignaciones permitidas de tipos de SQL a tipos Java que pueden ser utilizados por los ResultSet métodos getter.

Los nombres de columna utilizados como entrada a los métodos getter distinguen entre mayúsculas y minúsculas. Cuando un método getter se llama con un nombre de columna y varias columnas tengan el mismo nombre, el valor de la columna de primer apareamiento se devolverá. La opción de nombre de la columna está diseñada para ser utilizada cuando los nombres de las columnas se utilizan en la consulta SQL que generó el conjunto de resultados. Para las columnas que no están explícitamente mencionadas en la pregunta, lo mejor es utilizar números de columna. Si se usan los nombres de columna, no hay manera de que el programador garantice que en realidad se refieren a las columnas destinadas.

El método actualizador se puede utilizar de dos maneras:

1. para actualizar un valor de columna de la fila actual. En un desplazable ResultSet objeto, el cursor puede moverse hacia atrás y hacia delante, a una posición absoluta, o a una posición relativa a la fila actual. Las actualizaciones de código siguiente fragmento de la NOMBRE columna en la quinta fila del conjunto de resultados objeto

Page 3: RESULTSET(Administracion Base de Datos)

rs y luego utiliza el método updateRow para actualizar la tabla de origen de datos del que rs fue derivado.

rs.absolute (5); / / Mueve el cursor a la quinta fila de rs rs.updateString ("NOMBRE", "AINSWORTH"); / / actualiza los / / NOMBRE columna de la fila 5 para AINSWORTH rs.updateRow (); / / actualiza la fila del origen de datos

2. para insertar valores de columna en la fila de inserción. Un actualizable ResultSet objeto tiene una fila especial asociada con el que sirve como un área de ensayo para la construcción de una fila que se inserta. El fragmento de código siguiente se mueve el cursor a la fila de inserción, construye una fila de tres columnas, y lo inserta en rs y en la tabla de origen de datos usando el método insertRow.

rs.moveToInsertRow (); //se mueve el cursor a la fila de inserción rs.updateString (1, "AINSWORTH"); //actualiza los / / Primera columna de la fila de inserción para AINSWORTH rs.updateInt (2,35); / / actualiza la segunda columna a ser 35 rs.updateBoolean (3,true); //actualiza la tercera columna a cierto rs.insertRow (); rs.moveToCurrentRow ();

Un ResultSet objeto se cierra automáticamente cuando la declaración objeto que generó se cierra, vuelve a ejecutar, o se utiliza para recuperar el siguiente resultado de una secuencia de varios resultados.

El número, tipos y características de un ResultSet columnas de objetos se logran mediante la ResulSetMetaData objeto devuelto por la ResultSet.getMetaData método.

MÉTODOS

Next()

public boolean next()

Mueve el cursor una fila hacia abajo desde su posición actual. Un ResultSet cursor se coloca inicialmente antes de la primera fila, la primera llamada al método siguiente hace que la primera fila de la fila actual; la segunda llamada hace que la segunda fila de la fila actual, y así sucesivamente.

Page 4: RESULTSET(Administracion Base de Datos)

Si un flujo de entrada está abierto para la fila actual, una llamada al método siguiente implícitamente cerrarla. Un ResultSet cadena de objetos de advertencia se borra cuando el registro se lee.

Devuelve:true si la nueva fila actual es válido; false si no quedan más filas

Lanza:SQLException - si un error de acceso a la base de datos se produce

Close()

public void close ()

Publicaciones de este conjunto de resultados de base de datos objeto y los recursos JDBC inmediatamente en lugar de esperar a que esto suceda cuando se cierra automáticamente.

Nota: Un ResultSet objeto se cierra automáticamente por la Declaración de objeto que se genera cuando que Declaración de objeto está cerrado, vuelve a ejecutar, o se utiliza para recuperar el resultado siguiente de una secuencia de resultados múltiples. Un ResultSet objeto también se cierra automáticamente cuando es recolectado.

Lanza:SQLException - si un error de acceso a la base de datos se produce

getString

public Cadena getString (int columnIndex) Recupera el valor de la columna designada en la fila actual de este ResultSet objeto como una cadena en el lenguaje de programación Java.Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es nulo

Lanza:SQLException - si un error de acceso a la base de datos se produce

Page 5: RESULTSET(Administracion Base de Datos)

getBoolean

public boolean getBoolean (columnIndex int)

Recupera el valor de la columna designada en la fila actual de este conjunto de resultados como un objeto booleano en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es false

Lanza:SQLException - si un error de acceso a la base de datos se produce

getByte

public byte getByte (columnIndex int)

Recupera el valor de la columna designada en la fila actual de este ResultSet objeto como un byte en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es 0

Lanza:SQLException - si un error de acceso a la base de datos se produce

getShort

public short getShort (columnIndex int)

Recupera el valor de la columna designada en la fila actual de este ResultSet objeto como un corto en el lenguaje de programación Java.

Page 6: RESULTSET(Administracion Base de Datos)

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es 0

Lanza:SQLException - si un error de acceso a la base de datos se produce

getInt

public int getInt (int columnIndex)

Recupera el valor de la columna designada en la fila actual de este ResultSet objeto como un int en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es 0

Lanza:SQLException - si un error de acceso a la base de datos se produce

getLong

public short getLong (columnIndex int)

Recupera el valor de la columna designada en la fila actual de este ResultSet objeto como un tiempo en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es 0

Lanza:

Page 7: RESULTSET(Administracion Base de Datos)

SQLException - si un error de acceso a la base de datos se produce

getFloat

public float getFloat (columnIndex int)

Recupera el valor de la columna designada en la fila actual de este conjunto de resultados como un objeto flotante en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es 0

Lanza:SQLException - si un error de acceso a la base de datos se produce

getDouble

public double getDouble (columnIndex int)

Recupera el valor de la columna designada en la fila actual de este ResultSet objeto como un doble en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es 0

Lanza:SQLException - si un error de acceso a la base de datos se produce

getBigDecimal

public BigDecimal getBigDecimal (columnIndex int, scale int)

Desaprobado.  

Page 8: RESULTSET(Administracion Base de Datos)

Recupera el valor de la columna designada en la fila actual de este ResultSet como objeto java.sql.BigDecimal en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...scale - el número de dígitos a la derecha del punto decimal

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es nulo

Lanza:SQLException - si un error de acceso a la base de datos se produce

getBytes

public byte [] getBytes (int columnIndex)

Recupera el valor de la columna designada en la fila actual de este ResultSet objeto como un byte array en el lenguaje de programación Java. Los bytes representan los valores sin procesar devueltos por el controlador.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es nulo

Lanza:SQLException - si un error de acceso a la base de datos se produce

getDate

public Fecha getDate (columnIndex int)

Recupera el valor de la columna designada en la fila actual de este ResultSet como objeto java.sql.Date objeto en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...Devuelve:

Page 9: RESULTSET(Administracion Base de Datos)

el valor de la columna, y si el valor es SQL NULL , el valor devuelto es nulo

Lanza:SQLException - si un error de acceso a la base de datos se produce

getTime

public Time getTime (int columnIndex)

Recupera el valor de la columna designada en la fila actual de este ResultSet como objeto java.sql.Time objeto en el lenguaje de programación Java.

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:el valor de la columna, y si el valor es SQL NULL , el valor devuelto es nulo

Lanza:SQLException - si un error de acceso a la base de datos se produce

getWarnings

public SQLWarning getWarnings ()

Recupera el primer aviso reportado por las llamadas en esta ResultSet objeto. Advertencias posteriores sobre este ResultSet objeto será encadenado a la SQLWarning objeto que devuelve este método.

La cadena de advertencia se borra automáticamente cada vez que se lee una nueva fila. Este método no puede ser llamado un ResultSet objeto que se ha cerrado, si lo hace, se producirá un SQLException para ser lanzada.

Nota: Esta cadena de alerta sólo contiene advertencias causadas por ResultSet métodos. Cualquier advertencia causada por Declaración de métodos (como la lectura de parámetros OUT) será encadenado en la Declaración de objeto.

Devuelve:el primer aviso de SQL objeto reportados o nulo si no hay ninguno

Page 10: RESULTSET(Administracion Base de Datos)

Lanza:SQLException - si un error de acceso a la base de datos se produce o se invoca este método en un conjunto de resultados cerrada

clearWarnings

public void clearWarnings ()

Borra todas las advertencias presentes en este ResultSet objeto. Después de llamar a este método, el método getWarnings devuelve nulo hasta que una nueva advertencia se reporta para este ResultSet objeto.

Lanza:SQLException - si un error de acceso a la base de datos se produce

getCursorName

public Cadena getCursorName ()

Recupera el nombre del cursor SQL utilizado por este ResultSet objeto.

En SQL, una tabla de resultados se recuperan a través de un cursor que lleva su nombre. La fila actual de un conjunto de resultados se puede actualizar o borrar mediante una actualización posicionada / borrar declaración que hace referencia al nombre del cursor. Para asegurar que el cursor tiene el nivel de aislamiento adecuado para apoyar la actualización, el cursor SELECT declaración debe ser de la forma SELECT FOR

UPDATE . Si FOR UPDATE se omite, las actualizaciones posicionadas pueden fallar.

La API JDBC soporta esta característica SQL, proporcionando el nombre del cursor SQL utilizado por un ResultSet objeto. La fila actual de un ResultSet objeto es también la fila actual de este cursor SQL.

Nota: Si la actualización posicionada no es compatible, una SQLException es lanzada.

Devuelve:el nombre SQL para este conjunto de resultados del cursor del objeto

Lanza:SQLException - si un error de acceso a la base de datos se produce

Page 11: RESULTSET(Administracion Base de Datos)

getMetaData

public ResultSetMetaData getMetaData ()

Recupera el número, los tipos y las propiedades de este ResultSet columnas de objeto.

Devuelve:la descripción de este ResultSet columnas objeto

Lanza:SQLException - si un error de acceso a la base de datos se produce

getObject

public object getObject (int columnIndex)

Obtiene el valor de la columna designada en la fila actual de este ResultSet objeto como un objeto en el lenguaje de programación Java.

Este método devolverá el valor de la columna especificada como un objeto Java. El tipo de objeto Java será el tipo por defecto de objetos Java correspondiente al tipo SQL de la columna, a raíz de la asignación para los tipos integrados especificados en la especificación JDBC. Si el valor es un SQL NULL , el controlador devuelve un Java nulo .

Este método también puede ser usado para leer datos específicos de tipos de datos abstractos. En la API JDBC 2,0, el comportamiento del método getObject se extiende a materializar de datos de SQL tipos definidos por el usuario. Cuando una columna contiene un valor estructurado o distinto, el comportamiento de este método es como si fuera una llamada a: (.. columnIndex, this.getStatement () getConnection () getTypeMap ()) getObject .

Parámetros:columnIndex - la primera columna es 1, el segundo es 2, ...

Devuelve:un java.lang.Object sostiene el valor de la columna

Lanza:SQLException - si un error de acceso a la base de datos se produce

Page 12: RESULTSET(Administracion Base de Datos)

findColumn

public int findColumn ( String  columnName

Mapas de lo dado ResultSet nombre de la columna a su ResultSet índice de la columna.

Parámetros:columnName - el nombre de la columna

Devuelve:el índice de la columna del nombre de la columna dada

Lanza:SQLException - si el ResultSet objeto no contiene columnName o un error de base de datos de acceso se produce

isBeforeFirst

public boolean isBeforeFirst ()

Recupera si el cursor está delante de la primera fila en este ResultSet objeto.

Devuelve:true si el cursor está delante de la primera fila; false si el cursor está en cualquier otra posición o el conjunto de resultados contiene ninguna fila

Lanza:SQLException - si un error de acceso a la base de datos se produce

isAfterLast

public boolean isAfterLast ()

Recupera si el cursor está situado después de la última fila de esta ResultSet objeto.

Devuelve:true si el cursor está situado después de la última fila, false si el cursor está en cualquier otra posición o el conjunto de resultados contiene ninguna fila

Lanza:

Page 13: RESULTSET(Administracion Base de Datos)

SQLException - si un error de acceso a la base de datos se produce

isFirst

public boolean isFirst ()

Recupera si el cursor está en la primera fila de este ResultSet objeto.

Devuelve:true si el cursor está en la primera fila, false de lo contrario

Lanza:SQLException - si un error de acceso a la base de datos se produce

isLast

public boolean isLast ()

Recupera si el cursor está en la última fila de esta ResultSet objeto. Nota: Al llamar al método isLast puede ser costoso porque el controlador JDBC que tenga que buscar por delante una fila con el fin de determinar si la fila actual es la última fila del conjunto de resultados.

Devuelve:true si el cursor está en la última fila, false de lo contrario

Lanza:SQLException - si un error de acceso a la base de datos se produce

getRow

public int getRow ()

Recupera el número de la fila actual. La primera fila es el número 1, el segundo número 2, y así sucesivamente.

Devuelve:el número de fila actual; 0 si no hay ninguna fila actual

Lanza:

Page 14: RESULTSET(Administracion Base de Datos)

SQLException - si un error de acceso a la base de datos se produce

Absolute

public boolean absoluto (fila int)

Mueve el cursor al número de fila dada en este ResultSet objeto.

Si el número de fila es positivo, el cursor se mueve al número de fila dada con respecto al inicio del conjunto de resultados. La primera fila es la fila 1, el segundo es la fila 2, y así sucesivamente.

Si el número de fila es negativa, el cursor se mueve a una posición de la fila absoluta con respecto al extremo del conjunto de resultados. Por ejemplo, una llamada al método absolute (-1) posiciona el cursor en la última fila, una llamada al método absolute (-2) mueve el cursor a la fila siguiente a la última, y así sucesivamente.

Un intento de colocar el cursor más allá de la primera fila / última en el conjunto de resultados deja el cursor delante de la primera fila o después de la última fila.

Nota: Llamada absolute (1) es lo mismo que llamar primero () . Llamada absolute (-1) es lo mismo que llamar last () .

Parámetros:row - el número de la fila a la que el cursor debe moverse. Un número positivo indica el número de fila contando desde el comienzo del conjunto de resultados; un número negativo indica el número de fila contando desde el extremo del conjunto de resultados

Devuelve:true si el cursor está en el conjunto de resultados, false de lo contrario

Lanza:SQLException - si un error de acceso a la base de datos se produce, o el tipo de conjunto de resultados es TYPE_FORWARD_ONLY

previous

public boolean previous ()

Mueve el cursor a la fila anterior en este ResultSet objeto.

Page 15: RESULTSET(Administracion Base de Datos)

Devuelve:true si el cursor está en una fila válida, false si está desactivado el conjunto de resultados

Lanza:SQLException - si un error de acceso a la base de datos se produce o el tipo de conjunto de resultados es TYPE_FORWARD_ONLY

GetType

public int getType ()

Recupera el tipo de este ResultSet objeto. El tipo se determina por la Declaración de objeto que creó el conjunto de resultados.

Devuelve:ResultSet.TYPE_FORWARD_ONLY , ResultSet.TYPE_SCROLL_INSENSITIVE , o ResultSet.TYPE_SCROLL_SENSITIVE

Lanza:SQLException - si un error de acceso a la base de datos se produce

Page 16: RESULTSET(Administracion Base de Datos)

NIVEL DE AISLAMIENTO (ISOLATION LEVEL)

Las transacciones especifican un nivel de aislamiento que define el grado en que se debe aislar una transacción de las modificaciones de recursos o datos realizadas por otras transacciones. Los niveles de aislamiento se describen en función de los efectos secundarios de la simultaneidad que se permiten, como las lecturas de datos sucios o las lecturas fantasmas.

Los niveles de aislamiento de las transacciones controlan lo siguiente:

Si se realizan bloqueos cuando se leen los datos y qué tipos de bloqueos se solicitan.

Duración de los bloqueos de lectura.

Si una operación de lectura que hace referencia a filas modificadas por otra transacción:

Se bloquea hasta que se libera el bloqueo exclusivo de la fila.

Recupera la versión confirmada de la fila que existía en el momento en el que se inició la instrucción o la transacción.

Lee la modificación de los datos no confirmada.

Es el nivel de aislamiento (isolation level) de una transacción, el comportamiento de SQL Server en operaciones de lectura o de escritura, los diferentes niveles de aislamiento basados en bloqueos (READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE) y los niveles de aislamiento basados en versionado de filas (READ COMMITTED SNAPSHOT, SNAPSHOT), se explican los males de la concurrencia (lecturas sucias, lecturas no repetibles, lecturas fantasma, y conflictos de actualización), como establecer el nivel de aislamiento deseado (SET TRANSACTION ISOLATION LEVEL y las opciones de base de datos READ_COMMITTED_SNAPSHOT y ALLOW_SNAPSHOT_ISOLATION), cómo conocer el tiempo máximo de bloqueo (@@LOCK_TIMEOUT) y como establecer el tiempo máximo de bloqueo (SET LOCK_TIMEOUT), etc.

El nivel de aislamiento de una transacción (transaction isolation level) define el grado en que se aísla una transacción de las modificaciones de recursos o datos realizadas por otras transacciones. El nivel de aislamiento de una transacción es una característica de vital importancia en el desarrollo de aplicaciones de base de datos, ya que afecta a los tipos y duración de bloqueos que se producen en nuestra infraestructura de base de datos, lo cual, tiene efectos directos en el rendimiento y tiempo de respuesta de nuestras consultas y transacciones. Además, el nivel de aislamiento nos permite indicar cómo deseamos que

Page 17: RESULTSET(Administracion Base de Datos)

se comporte nuestro motor de base de datos frente a situaciones como las lecturas sucias (dirty reads), las lecturas no repetibles o las lecturas fantasma, comportamientos que pueden impactar consistentemente en la eficacia de nuestros desarrollos en entornos de base de datos con concurrencia. Evidentemente, la elección del modo de aislamiento es más importante cuanto mayor es la concurrencia de la base de datos (sin concurrencia, ¿a quién le interesan los modos de aislamiento?).

Es importante entender perfectamente el comportamiento por defecto de SQL en las operaciones de lectura y de escritura:

En operaciones de escritura. Siempre se obtiene un bloqueo exclusivo que se mantiene hasta que se completa la transacción.

En operaciones de lectura. El comportamiento dependerá del nivel de aislamiento de la transacción. Por defecto, SQL Server utiliza el modo de aislamiento basado en bloqueos READ COMMITTED, que se explica un poco más adelante.

SQL Server 2005 ofrece seis niveles de aislamiento diferentes, que podemos agrupar en:

Niveles de Aislamiento basados en bloqueos. Se trata del comportamiento tradicional de SQL Server (existente desde versiones anteriores de SQL Server), como se ha descrito en el párrafo anterior. El funcionamiento de SQL Server se basa en el establecimiento y gestión de los bloqueos. Existen cuatro modos de aislamiento diferentes basados en bloqueos cubiertos en la norma SQL-99 : READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ y SERIALIZABLE.

Niveles de Aislamiento basados en versionado de filas (row versioning - similar a ORACLE). Desde SQL Server 2005 están disponibles dos nuevos niveles de aislamiento: READ COMMITTED SNAPSHOT y SNAPSHOT. Estos dos nuevos niveles de aislamiento se basan en el versionado de filas (row versioning). Una de las principales razones de utilizar el versionado de filas (row versioning) es minimizar los bloqueos ocurridos en la base de datos, con el fin de obtener un mejor rendimiento (las operaciones de lecturas, sólo establecerán bloqueos compartidos de esquema a nivel de tabla, y NO bloquearán filas ni páginas de datos). Siempre que una transacción modifica un fila en uno de los modos de aislamiento de versionado de filas, SQL Server 2005 utiliza TEMPDB para almacenar una copia de la fila con el valor original y el número de secuencia de la transacción. En caso de que múltiples transacciones modifiquen la misma fila, se almacena en TEMPDB una cadena de valores de la fila. Las operaciones de lectura podrán acceder a la versión apropiada de cada fila (accediendo a TEMPDB si es necesario) para así obtener datos congruentes sin necesidad de generar bloqueos. Para que encontremos más familiar el uso del versionado filas (row versioning), resulta de interés saber que SQL Server 2005 saca provecho del versionado de filas (row versioning) en el funcionamiento de las tablas virtuales inserted y deleted de los triggers, en las operaciones de índice con la cláusula ONLINE, etc.

Page 18: RESULTSET(Administracion Base de Datos)

Tanto para comprender bien los modos de aislamiento basados en bloqueos, como para comprender los modos de aislamiento basados en versionado de filas, es muy importante también comprender bien los conceptos de lecturas sucias (dirty reads), lecturas no repetibles (non repeatable reads) y lecturas fantasma (phantom reads). Estos conceptos se explican un poco más adelante.

A continuación se describen los cuatro posibles niveles de aislamiento basados en bloqueos.

READ UNCOMMITTED puede recuperar datos modificados pero no confirmados por otras transacciones (lecturas sucias - dirty reads). En este nivel se pueden producir todos los efectos secundarios de simultaneidad (lecturas sucias, lecturas no repetibles y lecturas fantasmas - ej: entre dos lecturas de un mismo registro en una transacción A, otra transacción B puede modificar dicho registro), pero no hay bloqueos ni versiones de lectura, por lo que se minimiza la sobrecarga. Una operación de lectura (SELECT) no establecerá bloqueos compartidos (shared locks) sobre los datos que está leyendo, por lo que no será bloqueada por otra transacción que tenga establecido un bloqueo exclusivo por motivo de una operación de escritura. Este nivel de aislamiento ofrece grandes beneficios de rendimiento, pero sólo deberemos utilizarlo en aquellos casos en que la ocurrencia de lecturas sucias (dirty reads) no sea un problema.

READ COMMITTED permite que entre dos lecturas de un mismo registro en una transacción A, otra transacción B pueda modificar dicho registro, obteniendose diferentes resultados de la misma lectura. Evita las lecturas sucias (dirty reads), pero por el contrario, permite lecturas no repetibles. Es la opción por defecto en SQL Server 2000 y SQL Server 2005. Con este nivel de aislamiento, una operación de lectura (SELECT) establecerá bloqueos compartidos (shared locks) sobre los datos que está leyendo. Sin embargo, dichos bloqueos compartidos finalizarán junto con la propia operación de lectura, de tal modo que entre dos lecturas cabe la posibilidad de que otra transacción realice una operación de escritura (ej: UPDATE), en cuyo caso, la segunda lectura obtendrá datos distintos a la primera lectura (lecturas no repetibles).

REPEATABLE READ evita que entre dos lecturas de un mismo registro en una transacción A, otra transacción B pueda modificar dicho registro, con el efecto de que en la segunda lectura de la transacción A se obtuviera un dato diferente. De este modo, ambas lecturas serían iguales (lecturas repetidas). Para ello, una operación de lectura (SELECT) establecerá bloqueos compartidos (shared locks) sobre los datos que está leyendo, y los mantendrá hasta el final de la transacción, garantizando así que no se produce lecturas no repetibles (non repeatable reads). Mayor consistencia en la transacción, mediante mayores recursos y bloqueos (se evitan los problemas de las lecturas sucias y de las lecturas no repetibles, pagando el precio de necesidad de mayores recursos). Sin embargo, este modo de aislamiento no evita las lecturas fantasma, es decir, una transacción podría ejecutar una consulta sobre un rango de

Page 19: RESULTSET(Administracion Base de Datos)

filas (ej: 100 filas) y de forma simultánea otra transacción podría realizar un inserción de una o varias filas sobre el mismo rango.

SERIALIZABLE garantiza que una transacción recuperará exactamente los mismos datos cada vez que repita una operación de lectura (es decir, la misma sentencia SELECT con la misma cláusula WHERE devolverá el mismo número de filas, luego no se podrán insertar filas nuevas en el rango cubierto por la WHERE, etc. - se evitarán las lecturas fantasma), aunque para ello aplicará un nivel de bloqueo que puede afectar a los demás usuarios en los sistemas multiusuario (realizará un bloqueo de un rango de índice - conforme a la cláusula WHERE - y si no es posible bloqueará toda la tabla). Evita los problemas de las lecturas sucias (dirty reads), de las lecturas no repetibles (non repeatable reads), y de las lecturas fantasma (phantom reads).

En caso de trabajar con modos de aislamiento basados en bloqueo, es muy importante recordar que el tiempo de espera por un bloqueo por defecto en SQL Server es infinito. Es decir, si tenemos una transacción que está manteniendo un bloqueo sobre un recurso (ej: una fila particular de una tabla), y mientras una transacción B intenta acceder a dicho recurso (ej: a la misma fila), la transacción B se quedará en espera por un tiempo indefinido (o hasta que la transacción A libere dicho recurso). ¿A que ahora entendemos mejor porqué es modo de aislamiento READ UNCOMMITTED resulta tan atractivo, eh? Es posible establecer un tiempo de espera de bloqueo máximo, con el fin de evitar esperas largas en las transacciones. Para ello, es posible utilizar la sentencia SET LOCK_TIMEOUT para especificar el tiempo máximo de espera por bloqueo (en milisegundos). En caso se que una transacción alcance el tiempo máximo de espera por bloqueo, se producirá un mensaje de error 1222 (Msg 1222, Level 16, State 51, Line 1. Lock request time out period exceeded.). También es posible conocer el actual tiempo de espera por bloqueo, consultando el valor de la función del sistema @@LOCK_TIMEOUT.

A continuación se describen los dos posibles niveles de aislamiento basados en versionado de filas (row versioning).

SNAPSHOT. Evita los problemas de las lecturas sucias (dirty reads), de las lecturas no repetibles (non repeatable reads), y de las lecturas fantasma (phantom reads). Sin embargo, en vez de realizar un uso intensivo de bloqueos, su funcionamiento se basa en el almacenamiento de versiones de filas en TEMPDB. Si una transacción empieza en un momento del tiempo determinado, sólo será capaz de acceder a la información de la base de datos que era real en aquel momento del tiempo. Por ello, es posible que existan múltiples versiones de la misma fila en TEMPDB, con el fin de servir a múltiples transacciones. Debido al impacto que tiene este modo de aislamiento sobre la base de datos del sistema TEMPDB, sólo es recomendable en bases de datos intensivas en lecturas o en bases de datos con grandes problemas de bloqueos. Una situación de concurrencia particular de éste modo de aislamiento es el caso de los conflictos de actualización (update conflicts): Si una fila es leída en una transacción, y posteriormente como parte de la misma transacción es modificada, PERO entre la

Page 20: RESULTSET(Administracion Base de Datos)

lectura inicial y la posterior modificación ha sido alterada por otra transacción, se produce un conflicto de actualización (update conflict), que implica un mensaje de error 3960 (Msg 3960, Level 16, State 4 Line 1. Snapshot isolation transaction aborted due to update conflict. You cannot use snapshot isolation to access table 'myTable' directly or indirectly in database 'myDB' to update, delete or insert the row that has been modified or deleted by another transaction. Retry the transaction or change de isolation level for the update/delete statement), y además también implica que la transacción se dehace (Rollback).

READ COMMITTED SNAPSHOT. Se trata de una mezcla entre los modos de aislamiento READ COMMITTED y SNAPSHOT. Tiene la ventaja de utilizar el versionado de filas (row versioning), de tal modo, que las lecturas no son bloqueadas por las escrituras (y viceversa). Sin embargo, pueden producirse lecturas no repetibles (non repeatable reads) y lecturas fantasma (phantom reads). Es también importante tener en cuenta que en este modo de aislamiento, no se produce error en caso de conflictos de actualización (update conflicts).

¿Cómo se puede establecer el nivel de aislamiento en una transacción?

En SQL Server 2000, y para los cuatro modos de aislamiento basados en bloqueo (Read Uncommitted, Read Committed, Repeateable Read, Serializable), es suficiente con utilizar la sentencia SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATEABLE READ | SERIALIZABLE}.

En SQL Server 2005 se incluyen dos nuevas propiedades de base de datos (configurables a través del comando ALTER DATABASE). Se trata de las opciones de base de datos READ_COMMITTED_SNAPSHOT y ALLOW_SNAPSHOT_ISOLATION (ambas desactivadas por defecto - revisar el comando ALTER DATABASE de SQL Server 2005), de tal modo, que tenemos las siguientes opciones:

Activar READ_COMMITTED_SNAPSHOT (poner ON) y utilizar aislamiento READ COMMITED. La principal ventaja de éste método, es que al utilizar el nivel de aislamiento READ COMMITED (que es justo el modo de aislamiento por defecto en SQL Server), estaremos aprovechando las ventajas del versionado de filas (row versioning). Por ello, en muchos casos, simplemente será necesario activar la opción de base de datos READ_COMMITTED_SNAPSHOT (poner a ON) y disfrutar del versionado de filas (row versioning), sin necesidad de tocar el código de las transacciones.

Activar ALLOW_SNAPSHOT_ISOLATION (poner ON) y utilizar aislamiento SNAPSHOT. Requiere establecer de forma explícita el nivel de aislamiento SNAPSHOT, es decir, ejecutar SET TRANSACTION ISOLATION LEVEL SNAPSHOT. En caso del desarrollo de una aplicación nueva, es suficiente con tenerlo en cuenta, pero en caso de una aplicación existente, puede implicar tener que modificar el código fuente (algo que podría llegar a ser poco viable, según el caso).

Page 21: RESULTSET(Administracion Base de Datos)

Del mismo modo, también nos resultará muy útil ejecutar el comando DBCC USEROPTIONS y consultar sys.databases para poder conocer en qué modo de aislamiento estamos funcionando, y si las opciones de versionado están activadas en una u otra base de datos.

En la mayoría de los casos, será preferible utilizar el modo de aislamiento de lecturas confirmadas (READ COMMITED) junto con la opción de base de datos READ_COMMITTED_SNAPSHOT, debido a que:

Utiliza menos espacio en TEMPDB, que la utilización explícita del nivel de aislamiento SNAPSHOT (SET TRANSACTION ISOLATION LEVEL SNAPSHOT).

Soporta el funcionamiento de transacciones distribuidas, que no es soportado con la utilización explícita del nivel de aislamiento SNAPSHOT (SET TRANSACTION ISOLATION LEVEL SNAPSHOT).

Es fácil de implantar, ya que al activar la opción de base de datos READ_COMMITTED_SNAPSHOT, todas las transacciones que utilicen el nivel de aislamiento de lecturas confirmadas (READ COMMITTED - el nivel de aislamiento por defecto en SQL Server) se beneficiarán del aislamiento por versionado de filas (row versioning).

No es vulnerable ante conflictos de actualizaciones, mientras que por el contrario, con la utilización explícita del nivel de aislamiento SNAPSHOT (SET TRANSACTION ISOLATION LEVEL SNAPSHOT) si es posible que ocurran conflictos de actualizaciones. Es decir, si una transacción A lee una fila, seguidamente una transacción B actualiza dicha fila, y a continuación la transacción A actualiza la misma fila, la diferencia entre el aislamiento READ_COMMITTED_SNAPSHOT y el SNAPSHOT, está en si se produce un conflicto de actualización en la transacción A (finalizándose la transacción y realizándose ROLLBACK) o si ambas actualizaciones (de la transacción A y de la transacción B) se completan y confirman correctamente.