Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 22-06-2004
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Angry Transacciones y parámetros

Hola. He realizado un pequeño programa de prueba en Delphi 5 contra Firebird 1.03 utilizando IBX. El programa tiene un timer al que se la asigna un tiempo aleatorio (entre 1 y 3 segundos) de forma que en el evento del timer se produce el siguiente proceso:
1) Parar el timer
2) Iniciar transacción
3) update de un campo de unas tablas (se hace campo=campo+valor)
4) Aceptar transacción
5) Asignar un tiempo aleatorio al timer
6) habilitar el timer de nuevo.

La transacción tiene puestos los parámetros por defecto. Ejecuto el programa en varios ordenadores a la vez y obtengo al poco tiempo el error Deadlock. conflicts with concurrent update. En teoría este error no debería darlo, pues si se encuentra un recurso bloqueado durante una transacción debería hacer un "wait".
Suponiendo que no lo hace así, edito las propiedades de la transacción y le especifico los valores consistency y wait, para que haga las esperas. Lanzo la aplicación y obtengo el mismo error.

Cambio los componentes IBX por FIBPlus y da también errores de Deadlock (pero en menor medida), pero una vez que paro la aplicación y calculo cuantas veces se ha ejecutado la actualización en cada equipo veo que no coincide el valor final con el que debería ser.
Nota: cada vez que da error hago un rollback para deshacer la transacción.

Reviso los parámetros de las transacciones y creo que he puesto los correctos: consistency y wait que son los que me permiten lecturas repetibles y esperar frente a registros sucios. También lo pruebo con los parámetros por defecto que trae el componente de transacción.
Pues no entiendo porqué sucede esto. Y es un problema pues si las transacciones no funcionan bien, por ejemplo si varios procesos actualizan un saldo de forma simulatánea, no se garantiza que el valor final sea el correcto.
Primera pregunta: ¿esto es así o me estoy equivocando en algo? A la vista de las pruebas no sé que pensar.

Esto me lleva a plantearme la posibilidad de tener un tabla de semáforos para saber si puedo o no actualizar una tabla porque haya otro actualizándola. Pero claro, con la tabla de semáforos me encuentro en la misma situación al ser un recurso compartido. Es decir, necesitaría poder bloquear la tabla para acceso exclusivo. ¿Otro parámetro de la transacción "lock"?
Segunda pregunta: ¿como implemento un semáforo con tablas firebird?

Gracias.
Responder Con Cita
  #2  
Antiguo 24-06-2004
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Question Replanteamiento del problema.

Hola. Replanteo el problema que he expuesto para ver si alguien le ha ocurrido lo mismo y saber como lo ha solucionado.
Supongamos que tenemos una tabla de artículos y uno de los campos es el stock actual de cada artículo. Desde varios equipo se realizan ventas de artículos, lo que repercute en acceder a dicho campo y disminuir el stock en la cantidad vendida. Por otra parte otros ordenadores están introduciendo compras, lo que repercute en el aumento de ese campo stock para cada artículo en concreto. Básicamente esto es lo que he simulado con la prueba descrita en el post anterior. Un registro que es actualizado simultáneamente desde varios equipos. El resultado final de las actualizaciones debe dejar un valor correcto de stock. Las premisas son las mismas:
- Las transacciones deben durar poco tiempo (el tiempo del update).
- Los recursos se toman y liberarn en el mismo orden (primero se actualiza una tabla y después la otra).
- Una transacción debería esperar (hacer wait) hasta que puediese actualizar el campo correspondiente, cuando otra transacción concurrente lo liberarse.

En el caso de tener configurado la transacción como No Wait, se captura la excepción y se genera un rollback que debería deshacer todo lo hecho.

Pues bien, la prueba que he hecho es básicamente lo descrito, pero si al final se mira el valor del campo que se incrementa y decrementa, el resultado no es el correcto, aun restando (por supuesto) las veces que dió error de deadlock (que por otra parte no debería dar pues puse la opción wait en la transacción ).

Alguien habrá resuelto esta cuestión de alguna manera ¿no?.
Gracias.
Responder Con Cita
  #3  
Antiguo 24-06-2004
valentine valentine is offline
Miembro
 
Registrado: abr 2004
Ubicación: Madrid
Posts: 38
Poder: 0
valentine Va por buen camino
Hola,


Yo he tenido un problema parecido, cuando ejecutaba una modificación de vez en cuando tambien me daba un deadlock, era debido al objeto que estaba utilizando, que objeto están usando??
Responder Con Cita
  #4  
Antiguo 25-06-2004
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
El deadlock que se obtiene es de la base de datos. Los componentes que he usuado han sido IBX y FIBPlus (para dos pruebas separadas).
Responder Con Cita
  #5  
Antiguo 25-06-2004
brandolin brandolin is offline
Miembro
 
Registrado: jul 2003
Ubicación: Mendoza
Posts: 324
Poder: 21
brandolin Va por buen camino
He desarrollado varios sistemas en diferentes tipos de archivos de base de datos y el problema existencial que tuve es el de las actualizaciones de stock hechas desde las estaciones.

Ahora uso Firebird 1.5 y el problema lo he resuelto utilizando un trigger, asi el la cuenta del stock lo hace el mismo motor de base de datos y el cliente se olvida del problema.

Espero que te sirva la idea.

Gracias.
Responder Con Cita
  #6  
Antiguo 28-06-2004
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Hola. Pero según creo entender, ¿tu reacalculas en cada momento el stock del artículo antes de mostrárselo al usuario? No te he entendido bien.
Responder Con Cita
  #7  
Antiguo 22-07-2004
sur-se sur-se is offline
Miembro
 
Registrado: may 2003
Posts: 212
Poder: 21
sur-se Va por buen camino
Solucionado

Hola, he instalado Firebird 1.5.1 he puesto los componentes FIBPlus y configurado las transacciones como isc_tpb_read_committed y isc_tpb_wait. El problema ha desaparecido ya y las actualizaciones las hace correctamente, ejecutando los bloqueos bien. Parece que el F 1.5.1 va estupendamente.
Saludos.
Responder Con Cita
  #8  
Antiguo 22-07-2004
Avatar de guillotmarc
guillotmarc guillotmarc is offline
Miembro
 
Registrado: may 2003
Ubicación: Huelva
Posts: 2.638
Poder: 24
guillotmarc Va por buen camino
Hola.

No te puedo ayudar mucho con la configuración de transacciones con IBX y FIBPlus, puesto que no los utilizo.

Aunque el tema de asegurar el bloqueo de una tabla o un registro, lo puedes conseguir con un bloqueo pesimista. Consulta la página 13 de las Release Notes de Firebird 1.5.

Finalmente, el tema del cálculo de Stocks yo también lo realizo en Triggers (como ha comentado brandolin), y no se recalcula cada vez que consultas el Stock, sinó solamente cada vez que se dispara el trigger.

Saludos.
__________________
Marc Guillot (Hi ha 10 tipus de persones, els que saben binari i els que no).
Responder Con Cita
  #9  
Antiguo 22-07-2004
celades celades is offline
No confirmado
 
Registrado: may 2003
Ubicación: Torroella de Montgrí (Girona)
Posts: 42
Poder: 0
celades Va por buen camino
Hola

Yo el tema de estocs lo resuelvo con una tabla temporal
Imaginemos que voy entrando lineas de albaran, al grabar la linea en Delphi lo que hago es grabar la linea en el temporal con otra transaccion y hago commit en la misma.
Con lo que si alguien consulta el estoc del articulo de la linea le muesto que quedan lo del estoc del articulo- todas las ventas del temporal +todas las compras del temporal con lo cual el estoc que muestro ( no el que tiene el registro del articulo ) siempre lo tengo actualizado al instante.
Si al final cancelo la entrada del albaran, simplemente borro las lineas del temporal con su transaccion y commit de la misma i rollback de la transaccion del albaran
Si al final valido el albaran hago commit de la transaccion del albaran
y anulo las lineas del temporal previo descuento del stoc del registro del articulo de la linea del temporal borrada i commit de su transaccion.

Espero haberme explicado pero yo es la manera que encontre de evitar deadlock sin hacer commit de la transaccion del albaran y a la vez evitar poder vender una unidat de estoc dos vendedores a la vez. Todo lo hago lanzando procedimientos adecuados pero la clave son las dos transacciones una en la que puedo hacer rollback y la otra con commits cada vez.

En fin cada uno se lo monta como puede, supongo que habra sistemas mas limpios, que este que es sui-generis mio.

Saludos
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


La franja horaria es GMT +2. Ahora son las 05:38:04.


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