Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 03-04-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
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 !
Responder Con Cita
  #2  
Antiguo 03-04-2007
Avatar de Caral
[Caral] Caral is offline
Miembro Premium
 
Registrado: ago 2006
Posts: 7.659
Poder: 25
Caral Va por buen camino
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
Responder Con Cita
  #3  
Antiguo 03-04-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
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 !
Responder Con Cita
  #4  
Antiguo 03-04-2007
[egostar] egostar is offline
Registrado
 
Registrado: feb 2006
Posts: 6.561
Poder: 25
egostar Va camino a la fama
Este tema implica varias cosas.
  • Necesitas saber si se va a reservar por habitación o por tipo de habitación.
  • Necesitas una tabla de reservas donde indiques [tipo] o [numero] de habitación, fecha de ingreso y noches reservadas.
  • Si la reserva es con garantía o sin garantía, eso es muy importante.
  • Si es con un paquete o plan
En fin, yo no creo que necesites dos transacciones, tu generas la reserva y se debe actualizar en todos las aplicaciones cliente, la reserva debería de permanecer hasta que es cancelada por el cliente que la solicitó, o con un limite de tiempo si no está garantizada, si está garantizada no hay problema porque si no se presenta el huesped, se genera lo que se llama "No Show".

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
Responder Con Cita
  #5  
Antiguo 03-04-2007
Avatar de ArdiIIa
[ArdiIIa] ArdiIIa is offline
Miembro Premium
 
Registrado: nov 2003
Ubicación: Valencia city
Posts: 1.481
Poder: 22
ArdiIIa Va por buen camino
Cita:
Empezado por gluglu
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.
A lo mejor esto te aclara algo...
__________________
Un poco de tu generosidad puede salvar la vida a un niño. ASÍ DE SENCILLO
Responder Con Cita
  #6  
Antiguo 03-04-2007
Avatar de Caral
[Caral] Caral is offline
Miembro Premium
 
Registrado: ago 2006
Posts: 7.659
Poder: 25
Caral Va por buen camino
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
Responder Con Cita
  #7  
Antiguo 04-04-2007
Mick Mick is offline
Miembro
 
Registrado: may 2003
Posts: 405
Poder: 22
Mick Va por buen camino
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.
Responder Con Cita
  #8  
Antiguo 04-04-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
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:
  1. Muestro al cliente el número de habitaciones disponibles
  2. El cliente escoge cuántas habitaciones reserva.
  3. El cliente oprime Aceptar
  4. Inicio una transacción
  5. Resto al número de habitaciones disponibles el número solicitado.
  6. Consulto el número de habitaciones que queda después de la resta
  7. Si es negativo quiere decir que alguien más se adelantó, de manera que hago un rollback de la transacción y mando un aviso al cliente.

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.
Responder Con Cita
  #9  
Antiguo 04-04-2007
[egostar] egostar is offline
Registrado
 
Registrado: feb 2006
Posts: 6.561
Poder: 25
egostar Va camino a la fama
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
Responder Con Cita
  #10  
Antiguo 04-04-2007
luisgutierrezb luisgutierrezb is offline
Miembro
 
Registrado: oct 2005
Ubicación: México
Posts: 925
Poder: 19
luisgutierrezb Va por buen camino
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...
Responder Con Cita
  #11  
Antiguo 04-04-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
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.
Responder Con Cita
  #12  
Antiguo 04-04-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
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:

READ COMMITED NO RECORD_VERSION
: La transacción tiene acceso
a los registros modificados por otras transacciones que se estén ejecutando
concurrentemente. Si los cambios aún no han sido confirmados (
commit),
y la transacción tiene el parámetro
WAIT para la resolución de bloqueos,
esperará hasta que se confirmen (
commit) o rechacen (rollback). Si
por el contrario tiene el parámetro
NO WAIT, devolverá inmediatamente un
error a la aplicación cliente. En cualquier caso, una transacción nunca puede
tener acceso
real a registros modificados, pero no confirmados (commit);
InterBase
no soporta el llamado nivel de asilamiento READ UNCOMMITED,
también conocido como DIRTY READ.

Añado una nueva pregunta al hilo ... Firebird 2.0 soporta este tipo de 'Dirty Read' ??
__________________
Piensa siempre en positivo !
Responder Con Cita
  #13  
Antiguo 04-04-2007
Avatar de gluglu
[gluglu] gluglu is offline
Miembro Premium
 
Registrado: sep 2004
Ubicación: Málaga - España
Posts: 1.455
Poder: 21
gluglu Va por buen camino
Me contesto a mi mismo ...

He consultado la documentación de Firebird en esta página y he encontrado esto :
Cita:
Read locks - dirty reads Because records are tagged with their version and every transaction knows what transactions are currently active, no transaction can read a record version created by an active transaction. Dirty reads are impossible.
__________________
Piensa siempre en positivo !
Responder Con Cita
  #14  
Antiguo 04-04-2007
Mick Mick is offline
Miembro
 
Registrado: may 2003
Posts: 405
Poder: 22
Mick Va por buen camino
Cita:
Empezado por luisgutierrezb
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...
El tema que comentas no tiene mayor problema, esto se puede detectar mas o menos de forma facil de varias formas, ejemplo sencillo, tenemos una tabla llamadas HABITACIONES con un unico registro y un campo llamado CANTIDAD:

-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.
Responder Con Cita
  #15  
Antiguo 07-04-2007
d-hugo d-hugo is offline
Miembro
 
Registrado: abr 2007
Posts: 34
Poder: 0
d-hugo Va por buen camino
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.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

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


La franja horaria es GMT +2. Ahora son las 21:40:26.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi