Buenas tardes!!
Hace unos días, le consulte a Walter Ojeda, sobre la concurrencia en base de datos firebird, donde me explico como debe ser en su Blog, ya que en un tema explica el uso del campo TimeStamp y por mi confusión era lo que intentaba aplicar.
Por lo tanto replanteo la consulta en base a otra idea y doy mas detalles para que me puedan entender.
Tengo una tabla (puede ser cualquiera) por ejemplo CLIENTES, que es un catalogo, detallo como lo hago para ver de que forma lo resuelven ustedes.
UsuarioA, inicia transacción read only ...., hago un select a al cliente 1 llamado Juan, finalizo la transacción con un commit y el usuarioA ya tiene en pantalla en un formulario los datos del Cliente Juan
UsuarioB, inicia transacción read only ....., hago un select a al cliente 1 llamado Juan, finalizo la transacción con un commit y el usuarioB ya tiene en pantalla en un formulario los datos del Cliente Juan.
Resulta que el UsuarioA se fue a comer unos tacos al pastor, y el usuarioB hace cambios al registro modificando el nombre del cliente de JUAN a PEDRO, inicio una transacción READ WRITE ....., envió el UPDATE correspondiente y finalizo con un COMMIT. el usuarioB cierra la aplicación se va contento a comer.
Al rato regresa el usuarioA con dolor de panza porque comió muchos tacos, y en su pantalla tiene el registro del cliente 1 llamado todavía JUAN, le da editar y le pone el nombre MARÍA, le da guardar, entonces inicio una transacción READ WRITE ....., envió el UPDATE correspondiente y finalizo con un COMMIT. el usuarioA se va contento.
Pero al rato el usuarioB regresa consulta el registro e imprime y ve que aparece MARÍA, y se pregunta que paso?, porque si el usuarioA hubiera visto que ahora se llamaba MARÍA o que el sistema le hubiera informado que alguien hizo un cambio antes, ya el problema es interno y no del sistema.
Aquí el detalle es que incluso puedo hacer el primer SELECT y luego desconectarme del servidor y luego conectarme y enviar el UPDATE, por ello todo esta separado y una transacción no sabe que la otra hizo porque ya finalizo y se desconecto.
Explicación
Cuando el usuario busca un cliente me conecto al servidor, luego envió un "SET TRANSACTION READ ONLY SNAPSHOT WAIT, luego envió el SELECT para traer los datos del cliente y finalizo con un COMMIT y me desconecto del servidor, por lo tanto tiene en pantalla visualizando un registro.
Luego cuando el usuario va a guardar los cambios me conecto de nuevo e inicio un SET TRANSACTION READ WRITE READ COMMITTED WAIT, envió el UPDATE finalizo con un commit y desconecto del servidor, si no quiere guardar solo cierra el formulario. Por lo tanto en estos casos no hay transacciones activas que es lo recomendado e incluso conexión al servidor.
La nueva "solución" que estoy empleando es de nuevo usar un campo TimeStamp, pero ahora antes de enviar el UPDATE lo que hago es que envió un Select campoTimeStamp from clientes where id = 1 WITH LOCK , y luego verifico si la fecha es la misma y actualizo, si no es la misma entonces notifico al usuario que alguien mas modifico ese registro, de esta forma si un usuario dejo abierto el registro y lo modifica tendra un aviso, si dos usuarios al mismo tiempo intentan cambiar los datos de un mismo registro solo el primero le permitirá.
Detallo la solución:
Cuando el usuario busca un cliente me conecto al servidor, luego envió un "SET TRANSACTION READ ONLY SNAPSHOT WAIT, luego envió el SELECT y finalizo con un COMMIT y me desconecto del servidor.
Luego cuando el usuario va a guardar los cambios me conecto al servidor e inicio de nuevo con un SET TRANSACTION READ WRITE READ COMMITTED WAIT, pero ahora envió un Select campoTimeStamp from clientes where id = 1 WITH LOCK, verifico que la fecha sea igual y si lo es envió el UPDATE finalizo con un commit y desconecto del servido, si no es igual entonces aplico un Commit para finalizar la transacción porque no eh modificado nada, me desconecto del servidor y aviso al usuario que otro usuario hizo cambios al registro y le muestro los datos actuales.
Eh realizado pruebas y funciona perfecto, incluso si dos usuarios al mismo tiempo intentan guardar los cambios solo a uno le permitirá y al otro le enviara el mensaje, y el bloqueo dura unos milisegundos y solo afecta al registro actual y solo lo hago en cabeceras que son un solo registro, para nada lo haré con varios registros,
Que otra opción hay manejan ustedes?, cabe mencionar que el select with lock, lo hago a una busqueda por el campo ID (Primary Key) por ello es super rápido y solo me traigo el campo timestamp que necesito la consulta esta optimizada.
saludos
Antonio Meza