FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
||||
|
||||
Transacciones Concurrentes
Hola a todos !
Cómo tengo que definir dos transacciones diferentes para que una vea los cambios de la otra aun sin haber hecho un Commit ? Con Read_Committed, como su propio nombre indica, no puedo leer en una transacción los cambios que realiza otra hasta que no se aplica el Commit. Se trata de Reservas de Habitaciones en mi aplicación de reservas de hoteles. Si un usuario elige un número de habitación, inmediatamente tiene que aparecer que esa habitación está ocupada para los demás usuarios. Pero lo que quiero permitir es que el primer usuario pueda hacer un Rollback para volver a dejar las habitaciones libres que NO ha confirmado con Commit, en caso de que finalmente no confirme la operación. Supongo que el mismo caso se daría con una aplicación bancaria. Si alguien intenta sacar dinero de un cajero, para todos los demás tiene que aparecer como reducido de su saldo, para que no pueda haber extracciones simultáneas en dos cajeros diferentes. Pero si finalmente el usuario decide cancelar la operación, todo volverá a su estado original. Gracias por vuestra ayuda
__________________
Piensa siempre en positivo ! |
#2
|
||||
|
||||
Hola gluglu
Supongo que debe haber una determinada cantidad de habiaciones Yo haria una tabla con todas las habitaciones y que cada vez que se trate de reservar una habitacion, se indique un si o no. De esta manera cuando empiece el programa leera primero esta tabla y podra definir si esta o no reservada, esto lo haria con un timer con poco tiempo asi siempre se estaria actualizando. Saludos |
#3
|
||||
|
||||
Gracias Caral por responder.
Pero no es así como tengo planteada la aplicación. Sé que se puede hacer lo que yo pretendo con transacciones. Pero quiero evitar el commit de una para que la otra me pueda leer. Creo haber leido sobre el tema, pero no me acuerdo. He buscado también ya en el foro pero no encuentro la respuesta correcta. Por eso acudo a vuestra ayuda.
__________________
Piensa siempre en positivo ! |
#4
|
|||
|
|||
Este tema implica varias cosas.
En fin, tiene su complejidad esto de las reservaciones. Salud OS.
__________________
"La forma de empezar es dejar de hablar y empezar a hacerlo." - Walt Disney |
#5
|
||||
|
||||
Cita:
__________________
Un poco de tu generosidad puede salvar la vida a un niño. ASÍ DE SENCILLO |
#6
|
||||
|
||||
Bueno
Aqui trabajo con piezas y estas pueden ser apartadas por cualquier cliente o directamente por la empresa. Lo que hago es crear una tabla en donde pongo la pieza reservada, asi la quito del inventario y no la puede apartar otro cliente. Tengo 8 clientes por internet y dos personas aqui, nunca he tenido un problema con los apartados. Me parece que esto del Commit trae mas complicaciones porque depende en mucho de la maquina y la base de datos, asi como del tiempo en el que se haga la transferencia. No se es nada mas una opinion. Saludos |
#7
|
|||
|
|||
No se si entiendo bien, pero eso de las reservas, implica que la transaccion no se confirmaria durante horas o dias, y eso no se puede hacer.
Entre el inicio de una transaccion y su commit o rollback, no deben pasar mas de unos pocos milisegundos o decimas de segundo. El sistema de transacciones no esta pensado para hacerlas de horas o dias, si la aplicacion pierde la conexion con la base de datos, las transacciones en curso se cancelan, se hace un rollback automatico. Asi que si se te apaga el servidor o un cliente se queda sin red perderias todas las reservas pendintes de los clientes. En cuanto al tema del banco, no se trabaja asi, el cliente hace lo que tenga que hacer, y solo en el ultimo milisegundo, cuando pulsas el boton aceptar, se comienza la transaccion , se hace lo que sea y lo mas rapidamente posible, en cosa de decimas de segundo o segundos a lo sumo , se confirma (o se cancela si hay algun problema). Que pasa si coinciden dos operaciones en el mismo momento sobre la misma cuenta bancaria (sobre el mismo registro de la base de datos) ??, pues que en el mismo momento no es posible que se den, a lo sumo una puede entrar unos nanosegundos o milisegundos mas tarde que otra, pues simplemente la que entre mas tarde ESPERA a que finalize la primera transaccion (que se haga commit o rollback), que sera normalmente cosa de decimas de segundo como mucho y despues se realiza la segunda. Esto precisamente es lo que garantiza que el saldo sea coherente. Normalmente a mayores hay un timeout, si una transaccion tiene que esperar a que finalize otra mas de X segundos, pues se aborta la transaccion y se da un error al usuario indicando que no se puede realizar la operacion solicitada, o se espera un poco y se reintenta. Imaginate que usasen los bancos un sistema como el que pretendes, imaginate que se te queda tonto el ordenador del cajero cuando esta atendiendo a un cliente, y todo el resto de operaciones de entrada o salida de dinero sobre esa cuenta tuviesen que quedar ahi esperando horas o dias a que reparasen el cajero . En definitiva creo que estas enfocando mal el problema. Yo creo que lo mas sencillo es que escribas simplemente en una tabla que tal cliente o tal puesto, tiene seleccionada tal habitacion por x segundos o x minutos o x horas. Para ello apuntas la habitacion, quien la tiene seleccionada y la fecha/hora en la que caducara esta seleccion. De este modo queda bloqueada la habitacion durante ese tiempo como mucho, el resto de puestos podran leerla pero no podran Selecionarla debido a que ven que esta seleccionada por otro puesto y que esta seleccion aun no ha caducado (aun no ha llegado la hora de caducidad). Esto funciona incluso aunque se bloquee uno de lospuestos de gestion, ya que se desbloquearia automaticamente la habitacion en cuanto llegase la fecha/hora fijada. Un Saludo Última edición por Mick fecha: 04-04-2007 a las 00:50:06. |
#8
|
||||
|
||||
Según yo entiendo, hay aquí una confusión con el término "confirmación".
Por un lado está la confirmación que un cliente puede hacer de las reservaciones que haya hecho previamente. Esto es, hoy reservo tres habitaciones y pasado mañana confirmo la reservación. En ese caso, aplica lo dicho por egostar y Mick. Pero, por otro lado, está la confirmación de la operación al momento de reservar. Es decir, yo entro al sistema, digo que quiero reservar tres habitaciones y oprimo el botón Aceptar (commit) o Cancelar (rollback), es decir, confirmo que reservo las habitaciones. Me parece que es a esto último a lo que se refiere gluglu. En todo caso, aplica lo que comenta Mick, la transacción debe durar lo menos posible. Lo que yo hago en una situación similar- que no igual, pues nada tiene que ver con reservaciones -es:
Desde luego que sería un caso hipersimplificado puesto que las reservaciones no se hacen nada más en cuanto al número de habitaciones, sino también de lapsos de días que se ocuparán, pero el punto es que durante la transacción ya no hay ninguna intervención del usuario y todo se hace en cuestión de milésimas de segundo. // Saludos Última edición por roman fecha: 04-04-2007 a las 01:10:07. |
#9
|
|||
|
|||
Claro, por eso he dicho que no creo necesario hacer lo que gluglu comenta, definir dos transacciones, la reserva se genera y listo, lo demas es proceso normal y como el cliente lo pida.
Salud OS.
__________________
"La forma de empezar es dejar de hablar y empezar a hacerlo." - Walt Disney |
#10
|
|||
|
|||
Pues al restar habitaciones puede ser que alguien haya reservado la 2 y otro la 3 casi al mismo tiempo y por la resta el programa crea que le ganaron la habitacion, quiero imaginarme que se usa una BD "decente" la cual te debe soportar triggers y ahi en un before insert o before update segun como se manejen las tablas, que revise la habitacion, ya que ahi se haria la cola de actualizaciones a la BD...
|
#11
|
||||
|
||||
Muchísimas gracias a todos por responder.
Deseo aclarar varios asuntos : Antes de nada ... de momento utilizo Interbase 7.5 1. No estoy hablando de dos transacciones dentro del mismo programa para este caso. Estoy hablando de dos puestos de trabajo diferentes. La aplicación que estoy haciendo ahora, lleva funcionando más de 15 años en Clipper. La estructura en Delphi, o más bien la funcionalidad, pretende ser más o menos parecida. Por lo que agradezco enormemente los consejos de como hacer una cosa u otra pero en esto caso ese apartado lo tengo cubierto. Gracias una vez más por vuestros amables consejos. En mi caso particular, y en este momento más particular todavía, lo que estoy intentando hacer es asignar un número de habitación a una reserva ya creada. Esto lo permito en cualquier momento de la reserva, ya creada o en el momento de crearla, hasta el propio Check-In. Es decir, permito crear reservas sin pre-asignación de habitaciones concretas. Simplemente indicando el tipo y número de habitaciones. Cuando un usuario cualquiera de la red solicita se le muestren las habitaciones disponibles, se busca en la base de datos y se abre un nuevo form con los números de habitaciones disponibles para un periodo de fechas concreto. En ese mismo momento, cualquier otro usuario de la red puede estar intentando hacer la misma operación de asignación de habitaciones pero para otra reserva diferente (o puestos a ser extremos, incluso sobre la misma reserva ...), que se pudiera solapar en fechas (o incluso para las mismas fechas) con la reserva del otro usuario. Dos usuarios diferentes tienen abiertos cada uno su form que le muestra las habitaciones disponibles para el periodo de fechas de la reserva que estan tratando. Aquí aparece el problema. Si un usuario elige una habitación y el otro usuario pretende elegir la misma habtiación (para un periodo de fechas igual o solapado), al segundo se le tiene que indicar que otro usuario ha elegido ya previamente esa habitación para las fechas correspondientes. Pero lo que además deseo es que si el primer usuario, al final del proceso de asignación de habitaciones, decide no confirmar el proceso, pueda hacer un 'Rollback' y liberar de nuevo esas habitaciones seleccionadas. Es por ello que pretendía poder informar al segundo usuario de que la habitación ya ha sido elegida por otro usuario diferente, sin obligar al primero a tener que realizar un Commit. 2. Por supuesto no estoy hablando en ningún caso que una transacción se queda abierta tres días ni nada así. Cada reserva tiene su 'estado' de reserva propio, y puede estar confirmada, sin confirmar, check-in, check-out, o así hasta 11 estados diferentes. Cambiar el estado es una operación de modificación sobre una reserva como cualquier otra modificación de otro de los datos de la reserva. Pero si estoy utilizando componentes Data-Aware para mostrar datos de la reserva en pantalla, o tengo un error de conceptos muy grande, o no sé como hacer eso sin tener una transacción abierta. Por lo tanto, en mi caso, tengo una transacción abierta para cada reserva, al ser entre otras cosas una aplicación MDI. Esta transacción se mantiene activa mientras un usuario tiene 'abierta' una reserva en pantalla para consultas y/o modificaciones. Es este el caso al que ha hecho mención Román. No estoy hablando de cambiar el estado de una reserva a 'confirmada'. Estoy refiriéndome a que un usuario creando una reserva 'confirme' (commit) o 'anule' (rollback) una reserva que se está creando en ese momento. 3. En otros hilos sobre temas diferentes en estos últimos días (en concreto un hilo sobre saldos bancarios) se ha hablado de si es bueno mantener una tabla con 'saldos' (en unos casos bancarios) que en mi caso particular serían de habitaciones disponibles. Decidí hace más de 15 años que al menos para mi, no era 'bueno' mantener esa tabla. La razón principal en su momento fue por la 'inestabilidad' de ese tipo de tablas en Clipper. Estamos de acuerdo que hoy en día las bases de datos permiten mucha mayor estabilidad. Pero sigo teniendo decidido que no voy a mantener esa tabla de habitaciones disponibles, porque entre otras cosas no sólo permito reservas habitaciones por días, sino también cualquier otro 'objeto' por horas, por minutos, o por intervalos. Además de poder reservas incluso 'camas' particulares de una habitación con varias camas (en el caso de hoteles p.ej. Bed & Breakfast, donde sea posible solicitar una cama en vez de habitaciones). (Ay !! que tiempos aquellos en los que uno iba solito a Londres por ejemplo y dormía en una cama de una habitación compartida por otras 5 personas más que no conocías de nada !!) (Habría que denominar a eso hoy 'Low Cost Beds' ??!! ) Sigamos con el tema. Es por ello que si tengo un proceso de revisión de disponibilidad después de 'confirmar' la creación de una reserva. Tal y como también comenta Román. Pero sin tabla de habitaciones disponibles. Y por supuesto que debe ser posible que se permitan y se den situaciones de overbooking, al menos desde el punto de vista informático a nivel de programación. Otra cosa muy diferente es establecer esas reglas o no de overbooking a nivel de usuario. Pero a nivel informático (puro y duro desde el punto de vista de registros y base de datos), al menos como comento ahora, debe ser posible que dos usuarios diferentes estén realizando una reserva por un periodo de fechas igual o solapado que finalmente provoque una situación de overbooking, que será avisada de manera correspondiente y coherente cuando la situación lo requiera. Espero no haberme 'enrollado' demasiado. Muchas gracias de nuevo a todos por vuestros comentarios.
__________________
Piensa siempre en positivo ! Última edición por gluglu fecha: 04-04-2007 a las 11:45:24. |
#12
|
||||
|
||||
Añado ...
Gracias ArdiIIa. Ya conocía el documento de transacciones de nuestro compañero Kinobi. Lo he leido en varias ocasiones. Pero como siempre pasa en estos casos, uno siempre aprende algo nuevo al volver a leer de nuevo un documento que hayas podido leer previamente en varias ocasiones. Y he localizado lo siguiente ... Cita:
__________________
Piensa siempre en positivo ! |
#13
|
||||
|
||||
Me contesto a mi mismo ...
He consultado la documentación de Firebird en esta página y he encontrado esto : Cita:
__________________
Piensa siempre en positivo ! |
#14
|
|||
|
|||
Cita:
-Iniciar una transaccion -Digamos que queremos reservar 2 habitaciones: UPDATE HABITACIONES SET CANTIDAD=CANTIDAD-2 WHERE CANTIDAD>2 -Comprobamos el numero de registros que ha modificado el update, y si es igual a 0, no tenemos habitaciones libres suficientes y cancelamos la transaccion. Esto se puede aplicar igualmente al problema de gluglu, todo consiste en hacer el update con una condicion WHERE adecuada que no se cumplira si otro usuario ha realizado un update sobre el mismo registro antes, o si no se cumplen los requisitos (en este caso que haya menos habitaciones de las que queremos restar). Ni siquiera se necesitan usar transacciones si el proceso de reserva implica modificar un solo registro, solo harian falta transacciones en el caso de que haya que modifica mas de un registro. Última edición por Mick fecha: 04-04-2007 a las 14:01:42. |
#15
|
|||
|
|||
gluglu,
A menos que no te haya entendido, me parece que tu problema radica en que estás intentando abarcar demasiado con una transacción. Esto no es necesario ni recomendable. Las transacciones se idearon para conseguir que las operaciones sobre las bases de datos tuvieran las cuatro propiedades denominadas ACID (Atomicity, Consistency, Isolation, and Durability). Mi sugerencia (y puede no ser la mejor) es que informáticamente subdividas la operación: usa consultas y ClientDatasets para la introducción y modificación de datos en el formulario, y sólo en el momento preciso en que se vaya a escribir a la base de datos se inicia la transacción, se pasan los datos pertinentes de los ClientDatasets o controles a las tablas que corresponda y se hace el COMMIT, o ROLLBACK en caso de algún error. De esta manera la transacción tomará como máximo un par de segundos y de haber alguna condición que no permita hacer el commit, el usuario no tendrá que recomenzar desde cero. Verificar si la habitación ha sido asignada se resuelve con un simple SELECT. Para más seguridad, se puede volver a lanzar ese SELECT dentro de la transacción justo antes de asignar definitivamente la habitación, e incluso si se desea se puede programar un timer que ejecute regularmente dicha consulta durante todo el tiempo que el usuario tenga abierto el formulario (claro, que esto implicaría más tráfico en la red). La idea es usar las transacciones solo para las instrucciones que modifiquen la base de datos, como INSERT, UPDATE o DELETE. El resto de las cosas generalmente se puede resolver con consultas. Si es necesario actualizar muchos datos en cascada se pueden crear triggers. De lo contrario uno puede terminar con un montón de transacciones abiertas simultáneamente durante un largo rato, lo cual puede ser fuente de interminables frustraciones por problemas de concurrencia. Así que mejor evitarte todo esto desde ahora que estás diseñando el nuevo sistema (es el momento ideal). Espero haberte sido de alguna ayuda. Saludos, Hugo. |
|
|
Temas Similares | ||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Transacciones | juanmdq | Oracle | 3 | 12-01-2007 14:59:42 |
transacciones | Investigador | Conexión con bases de datos | 2 | 08-12-2006 01:02:08 |
Limitar número de usuarios concurrentes | mlara | Firebird e Interbase | 0 | 25-11-2006 21:13:38 |
conexiones concurrentes?? | andresenlared | Conexión con bases de datos | 1 | 02-08-2006 02:31:30 |
Control de usuarios concurrentes | Toni | Providers | 2 | 02-08-2004 15:43:17 |
|