Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Práctica No. 9
Objetivo: El participante implementará una aplicación en donde podrá experimentar con las transacciones propias
del manejo de una base de datos, y también realizará bloqueos a los registros de las tablas.
Instrucciones: Diseñe la interfaz que se muestra, respete los prefijos sugeridos para los objetos. inserte los objetos
que se muestran, modifique propiedades e inserte el código correspondiente.
Desarrollo:
Transacciones
Pensemos en un ejemplo de transacciones que se realizan con frecuencia en los entornos bancarios. Por
ejemplo, una transferencia de dinero entre dos cuentas implica por un lado una reducción del saldo de la
cuenta de origen y por otro lado un aumento de la cuenta de destino.
Pueden darse situaciones en las que, bien sea por errores de hardware, bien sea por inexistencia de fondos
o por parte del saldo de una cuenta que está inmovilizado (Cheques en transito por ejemplo), la transacción
que implica los dos movimientos debe deshacerse y todas las cuentas involucradas en la transacción deben
volver al estado que tenían antes de iniciarse dicha operación.
Desde la versión 4.0 de Visual Basic los métodos aplicables a las transacciones (BeginTrans,
CommitTrans y RollBack) se aplican al objeto WorkSpace de los objetos DAO.
En la mayor parte de los servidores, las transacciones mantienen bloqueos de registros cuya finalidad es
evitar que otros usuarios puedan modificar e incluso leer los datos modificados por una transacción hasta
que dicha transacción sea confirmada (CommitTrans) o revocada (RollBack).
Por lo tanto para evitar en lo posible estos bloqueos, deberemos poner algo de nuestra parte; no mantener
una transacción pendiente durante demasiado tiempo, ya que ese tiempo puede ser precioso para el resto
de los usuarios que desean acceder a registros que nosotros estamos modificando.
En este ejemplo vamos a ver cómo podemos utilizar los WorkSpaces para lanzar transacciones en Visual
Basic entre dos cuentas bancarias. En la primera operación realizaremos una resta de la primera cuenta,
mientras que en la segunda operación aumentaremos el saldo de la segunda cuenta.
Tabla: Cuentas
Nombre Tipo Tamaño Regla de Validación
IDCuenta Numérico Entero Largo
Titular Texto 40
Saldo Numérico Doble >0
Tabla: Movimientos
Nombre Tipo Tamaño
IDCuentaOrigen Numérico Entero Largo
IDCuentaDestino Numérico Entero Largo
Cantidad Numérico Doble
FechaHora Fecha/Hora
Concepto Texto 50
En la tabla de cuentas introducimos los datos de dos registros de prueba. Por ejemplo:
Tranferiremos varias veces 100 pesos desde la cuenta 1001 hacia la cuenta 1002. Al llegar a saldo cero en la
primera cuenta no se deberá incrementar la segunda, ya que no hay saldo físico en la primera cuenta.
ComandoSQL$ = "INSERT INTO Movimientos " & "(IDCuentaOrigen, IDCuentaDestino, Cantidad, FechaHora,
Concepto) VALUES (1001, 1002, 100,#" + CStr(Now) + "#, 'Transferencia')"
Banco.Execute ComandoSQL$, dbFailOnError
AL trangredirse la norma de que el saldo de la cuenta origen debe ser superior a cero, aparecerá el siguiente
mensaje de la aplicación:
Acceso Multiusuario
En toda Base de datos en la que operan simultáneamente varios usuario se da el problema del acceso
concurrente a la información. Por ejemplo, imaginemos que dos usuarios están accediendo a la vez al mismo
registro para modificarlo. Si ese registro contiene información sobre el precio de un producto, ¿Qué sucederá
tras ambas modificaciones¿
Hace años, determinadas aplicaciones pensadas para el funcionamiento monousuario llegaban hasta extremos
de bloquear la máquina cuando dos usuarios accedían al mismo registro. Ese era el caso de aplicaciones
escritas en las primeras versiones de Basic o de Borland Turbo Pascal para el sistema operativo MSDOS 2.0 y
con las modificaciones de sistema de MultiLink. En dichas aplicaciones, en las que no se contemplaba el
problema multiusuario, al realizarse la escritura al mismo tiempo, el sistema operativo entraba en un
deadlock( Bloqueo de máquina de tipo bucle infinito que no reacciona al teclado) dejando de atender a los
usuarios.
Una vez que los compiladores y el sistema operativo MSDOS contemplaron el tema de las interrupciones de
NetBIOS y la instrucción SHARE para compartir archivos, el problema del acceso multiusuario quedó reducido
a un tema de coherencia de base de datos.
La coherencia o congruencia se limita a formular en la práctica este tipo de preguntas: ¿Cuál es el resultado de
un listado en el que uno de sus registros está siendo borrado por uno de los usuarios? ¿De qué sirve modificar
el precio de un producto si antes de grabarlo otro usuario ha dado de baja dicho producto? ¿Se debería permitir
que mientras un usuario edita un registro otro usuario esté modificándolo?
La herramienta que puede ayudarnos a evitar que se produzcan estos casos es el bloqueo. La idea que anima
el concepto del bloqueo es la misma que la de la propiedad privada. En el momento en que un usuario edita un
registro, el registro pasa a ser propiedad del usuario. En el momento en que el usuario escribe el registro
modificado, libera su propiedad y otro usuario diferente puede apropiarse de la información ya modificada.
No debemos confundir bloqueo con la validez de los datos. Los datos siempre son válidos, independientemente
de si están o no bloqueados.
• El usuario Jorge edita un registro de un cliente para grabar un contenido diferente. Una vez que los datos
están en pantalla, decide ir a tomar un café.
• La usuario Dolores quiere leer el registro para saber la dirección del cliente pero no desea modificar los
datos. ¿Deberá esperar a que regrese Jorge? No!, utilizando SanpShot podrá accesar la información sin
esperar a que se retire el bloqueo.
• Un tercer usuario, Gonzalo, desea realizar una factura para ese mismo cliente que Jorge, inadvertidamente,
ha dejado bloqueado en su terminal de trabajo. Ya que la factura actualiza el campo de total de ventas del
cliente Gonzalo deberá esperar a que se retire el bloqueo.
En cambio el bloqueo optimista se realiza justo durante el tiempo que dura la escritura del Update. Esto quiere
decir que si deseamos evitar distracciones por parte de los usuarios que puedan llegar a mantener una base de
datos bloqueada mientras toman café, deberemos emplear este método.
Este tipo de bloqueo se establece mediante la instrucción LockEdits. Por defecto está en modo pesimista
(LockEdits = True) aunque por programa podemos establecer que sea optimista (LockEdits = False)
Ejecutemos dos veces el proyecto para tener dos instancias del mismo.
Una vez que en ambas aplicaciones tengamos por ejemplo el autor No. 4, pulsaremos en una de ellas el botón
bloquear para modificar. Esto nos validará las cajas de texto. Intentemos ahora el mismo registro en la otra
aplicación. Nos mostrará el mensaje de error:
Tras aparecer el mensaje de error, la aplicación se cerrará. Esto es lo que puede suceder si lo ejecutamos en
red y no colocamos el mecanismo de manejo de errores. Vamos a instroducir cambios al código para que pueda
manejar la cricunstancia de un bloqueo previo:
Ahora aparece un mensaje casí idéntico y el programa no se cierra como en el caso anterior
Escribiremos un proceso de manejo de error. EL método utilizado será el de extraer el nombre del usuario del
interior de la cadena de mensaje de error. Obviaremos el nombre de la máquina.
Sub Procesa(MensError$)
PosInicial% = 43
PosFinal% = InStr(MensError$, "on machine")
Usuario$ = Mid$(MensError$, PosInicial%, PosFinal% - PosInicial%)
MensajeNuevo$ = "El Usuario " + Usuario$ + " Esta Bloqueando el Registro"
MsgBox (MensajeNuevo$)
End Sub
El nombre de la máquina solo aparece cuando nuestra computadora pertenece a un grupo de trabajo. Pese a
ello, los bloqueos de registros funcionan siempre, garantizando la congruencia de los datos en el caso en que
incluso varias tareas dentro de una computadora monousuaria accedan al concurrentemente a los mismos
datos. De este modo, en el código fuente del botón de bloqueo y modificación haremos los siguientes cambios
Y podremos ver el siguiente mensaje de error ya modificado por el código anterior mediante el proceso Procesa.
Esta es una seria limitación de diseño del motor de Access y también de Microsoft SQL Server, el cual por
defecto realiza el bloqueo por páginas.
Si nuestro registro tiene una longitud de 2 Kbytes, el bloqueo de registro será igual al bloqueo por página, pero
si nuestro registro tuviera una longitud de 200 bytes, en una sola operación de edición bloquearíamos 10
registros consecutivos aproximadamente.
• Muchos problemas de lentitud de acceso se deben realmente al tiempo de reintento en las operaciones de
lectura y escritura multiusuario. Para mejorar este tiempo de acceso, debemos utilizar siempre que sea
posible SnapShots en lugar de DynaSets.
• Una transacción que realice una operación DELETE en SQL, por ejemplo, bloqueará todos los registros
afectados antes de borrarlos, en el momento que se realice un CommitTrans o un RollBack se liberarán.