ADO – Cursores, Bloqueos, Como elegirlos

Este es un Artículo en el tema ADO – Cursores, Bloqueos, Como elegirlos dentro de la Categoría General, Visual Basic 6.0, parte de El Código Fuente - PRIMERA PARTE Cuando de ADO se trata un lugar comun para muchos de nosotros es decidir, al momento de analizar estrategias de acceso a la data, que proveedor usar?, en que lugar correra el cursor; del lado del server? (Server side cursor?) o del lado del cliente (Client side cursor), que tipo de Cursor (Forward-Only, [&hellip...

Terminos de llegada:

cursores, adlockreadonly vb6, en vb6 cursor de un recordset, adlockoptimistic vb6 0, problemas de concurrencia vb6 0, que es adLockBatchOptimisti adOpenKeyset adLockOptimistic en visual basic 6 0

ADO – Cursores, Bloqueos, Como elegirlos

marzo 2, 2013 Sin Comentarios »
ADO – Cursores, Bloqueos, Como elegirlos

PRIMERA PARTE

Cuando de ADO se trata un lugar comun para muchos de nosotros es decidir, al momento de analizar estrategias de acceso a la data, que proveedor usar?, en que lugar correra el cursor; del lado del server? (Server side cursor?) o del lado del cliente (Client side cursor), que tipo de Cursor (Forward-Only, Static, Keyset o Dinamic?)… y por si fuera poco, aun nos falta decidir que tipo de Bloqueo usar (Locking ) (read only, pessimistic, optimistic o batchoptimistic?).

Todos los autores coinciden en que la decision no es simple y es mucho mas un problema de analisis del sistema que una aplicacion matematica.

Vamos por partes:

Que es un “CURSOR” para ADO?

Un CURSOR en terminos de bases de datos representa la manera de tratar un numero discreto de registros en forma de filas de data. El cursor le permite a uno moverse a traves del set de registros y posicionarse en uno de ellos para acceder a su data.

Al momento de elegir el cursor tenemos que decidir el lugar donde este correra (Cursor location), el comportamiento del mismo en terminos de moverse a traves del recorset (tipo de cursor) y su habilidad para permitir al usuario alterar la data original y la manera de hacerlo para evitar conflictos (Bloqueo o “Locking”).

Cursor Location. (Lugar donde correra el Cursor)

Para determinar el lado donde correra el cursor del recorset se debera implementar la propiedad CursorLocation del objeto recorset. Si no se especifica el rocorset tendra por “default” el valor que tenga la propiedad CursorLocation del objeto Connection que usara el recorset. El valor “default” (por defecto) de la propiedad CursorLocation del objeto Connetion es adUseServer (cursor del lado del server), que no siempre es el optimo.

Hay cuatro posibilidades de eleccion, pero nos enfocaremos en dos de ellos, ya que los otros dos son obsoletos, y a decir de MS se ha mantenido para efectos de compatibilidad con anteriores versiones

1 – adUseNone (obsoleto)
2 – adUseServer (default)
3 – adUseClient
3 – adUseClientBatch (obsoleto, pero no entiendo por que tiene el mismo numerico que anterior…no importa :-))

Entonces nos enfocaremos en los dos del medio.

Client-Side Cursors (3 – adUseClient, Cursores del lado del cliente)

Usa los recursos (memoria, cpu, etc.) de la maquina local (la del cliente), para implementar el cursor y su set de records.

Ventajas
- Dado que corre en la maquina del cliente la performance sera mejor si se trata de recorset de tamaño razonable (depende de la configuracion, basicamente de la memoria de la maquina para definir “razonable”).
- Tambien la escalabilidad del sistema se ve favorecida dado que la performance depende de cada maquina cliente y no del server, en consecuencia los cursores del lado del cliente exige menos demanda del server cuando el numero de clientes crece que cuando se usa el cursor del lado del Server (Server-side Cursor).
- Es el unico cursor que permite usar recorsets desconectados (de especial uso en N Tier systems).

Desventajas:
- Para recorset muy extensos (otra vez , extensos para una maquina cliente dependera de sus recursos), la estacion de trabajo podria tener problemas para manejar grandes volumenes de data.
- Dado que el cursor del lado del cliente tiene que traer la data a traves del network, recorsets grandes significaran un alto consumo del trafico del network. Esto es especialmente un problema cuando se usa la internet.
- No todos los “proveedores” manejan bien los Campos Autonumericos o Identity field (el proveedor de Jet si lo hace muy bien)

Server-side Cursors (2 – adUseServer (default), cursores del lado del server).

Usa los recursos del server para implementar el cursor y su set de records.

Ventajas
- Las maquinas del cliente o estaciones de trabajo no se veran en peligro con grades porciones de recorsets ya que el cursor es manejado totalemente el el server. (thin client)
- Dado que no toda la data es transferida al cliente el trafico del network no se ve sobrecargado.
- Para recorsets que se preven muy grandes es mejor manejarlos de esta manera

Desventajas
- Para recorsets pequeños es ineficiente ya que todo pedido de movimento tiene que se hecho a traves del network, en tal caso es mejor transferir todo el recorset al cliente (usando cliente-side cursor).
- Se presentan problemas de escalabilidad, miemntras mas usuarios se incremente an el sistema mas carga significara para el server, pudiendo de esta manera rapidamente consumirse los recursos del server.
- Problemas de concurrencia a la data, exige un mejor manejo de las conecciones. (se hace necesario el manejo del “pool” de conecciones y el uso de programas como el MTS).

SEGUNDA PARTE

En esta segunda parte escribire sobre los cuatro tipos de Cursores que ADO maneja, sus comportamientos y algunas otras consideraciones que pienso pertinentes tener en cuenta.

Tipo de Cursor (Curso type), en terminos de ADO, indica el comportamiento que tiene dicho Cursor, lo que se puede o no hacer con el y hasta se puede saber cuan liviano o pesado es en terminos de los recursos del sistema.

Se puede definir el tipo de Cursor a usar en un recorset, especificando la propiedad CursorType antes de abrir dicho recorset (no se puede cambiar el tipo de Cursor luego de que el recordset haya sido adquirido). El siguiente seria un ejemplo:

MiRecord.CursorType = adOpenOptimistic
MiRecord.Open

Existe, como ya dijimos en la primera parte, cuatro tipo de cursores en ADO:
Forward-Only, Static, Keyset y Dynamic.

Forward-Only. (adOpenForwardOnly)
Este tipo de cursor se comporta mas como un archivo secuencial y solo puede manipularse en la maquina del cliente de uno en uno y en estricto orden secuencial desde el primer record hasta el ultimo.

Vale decir que no se puede saltar records ni regresar a uno anterior, la unica manera de moverse es de uno en uno y partiendo del primer record hasta el ultimo.

Para enfatizar lo anterior debe pensarse que el unico metodo,respecto a movimiento entre registro,que se puede usar es MoveNext, cualquier otro intento generara un error (runtime error).

Cursor tipo Forward-Only es el cursor por default por que es el mas economico en terminos de recursos, sin embargo no esta disponible para Cursores en el lado del Cliente (Client Cursors).

MyRecord.CursorType = adOpenForwardOnly

Nota: Traten de usar este tipo de cursor si lo que necesitan solamente es mostrar datos (en grids o en reportes). una vez “poblados” sus variable u objetos entonces cierren el recorset para “liberar” recursos (incluso si pueden cerrar la coneccion, haganlo).

Static (adOpenStatic)
Es menos “economico” que Forward-Only pero tiene una gran flexibilidad en terminos de movimiento a traves del recorset. Podemos movernos por el recorset en todas las direcciones de uno en uno o saltar records, hacer filtros, busquedas, “bookmarks”.

Static es el unico cursor soportado por Cursores en el lado del Cliente (Client side Cursors),.

Una desventaja muy grande para este tipo de cursores se presenta en el hecho de que cualquier cambio hecho por otro usuario (o programa corriendo al mismo momento) no se ve reflejado en el recorset.

Esto es especialmente importante en ambientes multiusuarios donde, asumiendo que, por ejemplo, un usuario X abre un recorset con cursor “static” del lado del cliente, no le sera posible ver los cambios hechos por un usuario Y desde otra maquina, ya sean modificaciones adiciones o borrados (deletes) de dichos records. Entonces al momento de hacer Update el usuario X podria tener colisiones o conflictos que debera manejarlos mediande codigo (atrapando errores)

Nota: dos propiedades de el objeto Field de ADO ayudan a manejar este tipo de conflictos (Field.OriginalValue y Field.UnderlyingValue), el primero represanta el valor del campo cuando se solicito el record (sin considerar cualquier cambio que el usuario haga) mientras el segundo (y mas importante a lo hora de verificar cambios) representa el valor del campo en la misma base de datos incluyendo cualquier cambio que otro usuario haya hecho en el interin.

Hay ademas un par de maneras mas solucionar estos confictos uno de ellos es capturar los errores en el momento de hacer UpdateBatch. si un error ha ocurrido entonces podran hacer un filtro del recorset usando adFilterConflictingRecords que ver cuales de los registros han prentado problemas.

Keyset (adOpenKeyset)
Este tipo de cursores tienen la misma flexibilidad de “Static cursor” para el movimiento. Adicionalmente cualquier cambio hecho por otros usuarios a los records seran inmediatamente visibles por recorset activo; pero no se veran adiciones o borrados (deletes) hechos por otros usuarios.

Es obvio saber que un cursor de este tipo es mucho mas “costoso” en terminos de recursos de sistema, si a esto agregamos el hecho que este tipo de cursor solo puede ser usado en Cursores del lado del Server (Server side cursor) entonces tendremos un problema en terminos de “escalabilidad” ya que pocos usuarios podrian causar “atoros” en el server.

Dynamic (adOpenDynamic)
Caramba, por favor traten de evitarlo… :-), en verdad es muy “pesado”.
Tiene toda la flexibilidad del cursor tipo Keyset, con la ventaja de que se pueden “ver” ademas los borrados (deletes) o adiciones hechos por otros usuarios en el recorset.

Traten de evitarlo pues en terminos de “escalabilidad” es una calamidad.

TERCERA PARTE (ultima)

En esta tercera y ultima entrega escribire sobre las diferentes estrategias de bloqueo (locking strategies) que reconoce ADO para poder garantizar la integridad de la data.

Tambien, al finalizar, hare un resumen sobre algunos criterios que se pueden tener al momento de elegir un Cursor para el recorset (su lado, su tipo y su estrategia de bloqueo, “CursorLocation”, “CursorType” y “LockType”).

Estrategias de bloqueo (Locking Strategies)

En lo que refiere a ADO existen cuatro tipos de estrategias de bloqueo: Read-Only (solo para lectura), Pessimistic, Optimistic y Batch-Optimistic. (la propiedad LockType del objeto recorset debe ser establecida antes de abrir el recorset)

Ejemplo:

MiRocord.LockType = adLockReadOnly
MiRecord.Open

Las estrategias de bloqueo nos ayudan a garantizar la integridad de la data en el momento de actualizar la misma despues de manipularla mientras esta a nuestra disposicion a traves de un recorset. Sobre todo nos permitira elegir la estrategia que consideremos adecuada para evitar conflictos de data si es que dos o mas usuarios tratan de acceder y manipular la misma data al mismo tiempo.
Pintando esto un poco mas imaginemos que el vendedor A esta haciendo la venta de 3 unidades del producto X que en inventario se le presentan 5 unidades; por otro lado el vendedor B tambien esta haciendo una venta del producto X y necesita 4 unidades; aqui claramente hay un problema de “timing”, si ambos leen que hay 5 unidades en algun momento habra un conflicto de cantidades si ambos llegan a finalizar la venta. Las diferentes estrategias de bloqueo nos permitiran manejar este tipo de circunstancias de
una manera relativamente simple.

Read-Only (adLockreadOnly)
Cuando un cursor es abierto con esta opcion entonces el usuario no podra alterar ni adicionar ni borrar ninguno de los registros del recorset. Esto obviamente garantiza que no habra conflictos con cualquier manipulacion que otro usuario pueda hacer a la data en ese momento.
Este tipo de bloqueo es muy util cuando uno esta seguro que no se alterara la data (solo para consulta). Una combinacion de este tipo de bloqueo con un cursor tipo Forward-Only producira el cursor mas “economico” disponible en terminos de recursos (solo puede Cursor ser en el lado del Server). Usado ampliamente para consultas de data.

Pessimistic (adLockPessimistic)
Este tipo de bloqueo garantiza que ningun otro usuario podra manipular la data presente en nuestra recorset mientras este se ecuentra abierto. Este tipo de estrategia, si bien nos evita manipular conflictos puede ser un poco peligroso si un cliente deja abierto del recorset por mucho rato de tal manera que nadie mas pueda accesar a esa data y manipularla. (solo disponible el cursores del lado del server)

Optimistic (adLockOptimistic)
No hay ninguna garantia que el record en edicion no presentara conflictos al momento de hacer update (hay que usar las estrategias de captura de conflictos indicados en la segunda parte). El record solamente sera bloqueado mientras este en proceso de Update.

Batch Optimistic (adLockBatchOptimistic)
Para updates hechos con el metodo updateBatch del objeto recorset. Todos los cambios hechos al recordset se capturan en un cache desde el momento que se abre el recorset con esta estrategia de bloqueo; al momento de hacer UpdateBatch hay que analizar la coleccion de errores del objeto coneccion (Connection object) para capturar los conflictos que hayan ocurrido en el momento del Update.

ESCOGIENDO UNA OPCION DE CURSOR.

Como hemos visto a traves de estas tres entregas la eleccion de un cursor adecuado dependera basicamente de un buen analisis de las aplicaciones que tendra el sistema que se esta desarrolando.

Sera Monousuario?.. si es asi, se ampliara a sistemas multiusurio?, de ser multiusuario, habran muchos usuarios accesando a la misma data a la vez?, sera n sistema 2 Tier (dos capas?) o sera uno de N-tier (N capas).
Tambien podriamos no usar ningun tipo de Cursor en particular (que tal si usamos un sistema Client/server, donde todo la manipulacion de la data se hace en el server o en un server que se dedique a eso “Data server”).

En cualquier caso, lo que debemos tener en cuenta a la hora de elegir un cursor es Construir un cursor que use la menor cantidad de recursos posibles de todo el sistema y que aun sea util, que aun haga el trabajo bien.

Recuerden siempre que el mas economico de todos es el que combina Forward-Only con bloqueo Read-Only y corre del lado del servidor. Traten en lo posible de usar este tipo de cusores a partir de ahi y si necesitan mas recursos traten de usar otras alternativas que sean siempre economicas y hagan bien su trabajo.

Adicionalmente, yo recomendaria usar en lo posible Store Procedures (SP) y encargar al server todo el trabajo de actualizacion de data, incluyendo el manejo de posibles conflictos.

Hasta aca termino el presente articulo que espero sirva a algunos de nosotros como partida para entender un poco mas los diferentes “sabores” de ADO.

Fuente: Página de José Rubí

Comentar