PDA

Ver la Versión Completa : Como darle un Tiempo de Vida a un Bloqueo ????


AGAG4
16-08-2006, 21:28:38
Uso Firebird 1.53, D6, IBX 6.08
Tengo una Tabla de Consecutivos con la siguiente estructura:

Tabla_Consecutivos
Serie Folio
FM 1
FH 2

Tengo una Aplicación de Facturación, donde hace poco me paso un problema, mandaron una factura a grabar y antes de guardar bloqueo el folio de la factura, con el objetivo de que al bloquear dicho folio las demás computadoras se tienen que esperar hasta que se liberé, pero desgraciadamente cuando estaba bloqueado dicho Folio win98 marco el famoso error con fondo AZUL que decía algo de "VXD.... etc. etc." por lo que se bloqueo la computadora y por lo tanto las demás se quedaron bloqueadas esperando a ser liberado el folio, aqui no hubo de otra más que apagar las computadoras y reiniciar el Firebird Server del Servidor.

Mi pregunta es, habra algún parámetro ó configuración donde se le indique a Firebird que los bloqueos durarán X Segundos ó Minutos ???? con el objetivo de que no haya necesidad de Reiniciar el Firebird Server.

Agradezco cualquier sugerencia....

xander
16-08-2006, 21:57:18
Usa un generador para cada serie y asunto resuelto... solo mandas a generar el folio con el clasico GEN_ID(FM,1) y creas tantos generadores como series necesites... con estos ya no es necesario hacer bloqueos explicitos... de hecho creo que no es una buena práctica que uses una tabla para esto..

Es solo mi apreciación un experto ya te dirá como hacerlo

AGAG4
17-08-2006, 01:00:28
Yo uso esa tabla para tomar los FOLIOS REALES DE LAS FACTURAS no los folios internos, es por eso que no puedo usar los generadores, no se si has visto las formas de las facturas que ya vienen impresas con su FOLIO, esa es la razón principal de no usar generadores....

Gracias por tu sugerencia.

Mick
17-08-2006, 12:04:36
Esa es la principal razon por la que se desaconseja el uso de bloqueos pesimistas.
Si se usan bloqueos pesimistas hay que apechugar con los problemas que pueden provocar :(
Yo intentaria rehacer el sistema sin utilizar bloqueos pesimistas.

Saludos

AGAG4
17-08-2006, 16:18:21
Esa es la principal razon por la que se desaconseja el uso de bloqueos pesimistas.
Si se usan bloqueos pesimistas hay que apechugar con los problemas que pueden provocar :(
Yo intentaria rehacer el sistema sin utilizar bloqueos pesimistas.

Saludos

Rehacer el Sistema ???? :eek:

No sería mejor que me aconsejarás como puedo evitar que cuando se guarda una Factura otro usuario no tome el mismo folio ????

De los 2 años que tengo usando bloqueos pesimistas esta es la primer vez en que me he visto con problemas, espero no hayan otros más con motivo de los bloqueos pesimistas.

AGAG4
17-08-2006, 20:39:23
Encontre algo en el archivo Firebird.conf, hay un parámetro que se llama DeadLockTimeOut donde se le añade el tiempo en segundos de un bloqueo muerto, puediera ayudarme, voy a realizar pruebas. :)

bitbow
02-10-2006, 16:54:49
Dices que tu factura ya vienen con el folio de echo aqui se manejan igual, pero para que una tabla para guardar los folios, yo lo que hago es usar un id auntoinc para el identificador, un id_folio para las notas foliadas y seriarlas segun se ocupen en cada caja y un campo referencia en el cual se almacena el folio de factura en caso de que se emita una por esa venta, como no se que folio pudiera llegar a ocupar en determinado momento pues simplemente a la hora de facturar el usuario escribira el folio de la factura y lo guarda de esta forma no tengo que bloquear nada, bueno no soy un experto es esto de la facturacion y tal ves este mal pero asi es como vi que funcionaria mejor y no creo que al usuario le de un ataque por escribir unos numeros.

Saludos.

maeyanes
02-10-2006, 17:09:52
Yo estoy trabajando en un sistema de inventarios, donde los números consecutivos los genera la aplicación, basándome en una tabla de control. Cuando más de un cliente trata de guardar un registro nuevo, primero verifico si el número que voy a usar no está ya usado, si es así, obtengo un número nuevo y lo uso. Todo esto con un Trigger Before Insert de la tabla.

Ahora, desde la aplicación, al momento de guardar el registro lo hago mediante un repeat..until de esta forma:


repeat
Stored := True;
try
DataSet.Post;
except
on E: EIBInterBaseError do
begin
// Si existe DeadLock, cambio a False Stored para repetir la inserción...
Stored := not E.SQLCode = -901;
if Stored then // Si Stored sigue siendo verdadero, la excepción fue otra y la relanzo...
raise
end
end
until
Stored;


El código no es exactamente el mismo, pero con esto resolví el problema de los DeadLock...

Espero te sirva...


Saludos...

AGAG4
07-10-2006, 02:47:08
Yo estoy trabajando en un sistema de inventarios, donde los números consecutivos los genera la aplicación, basándome en una tabla de control. Cuando más de un cliente trata de guardar un registro nuevo, primero verifico si el número que voy a usar no está ya usado, si es así, obtengo un número nuevo y lo uso. Todo esto con un Trigger Before Insert de la tabla.

Ahora, desde la aplicación, al momento de guardar el registro lo hago mediante un repeat..until de esta forma:

Código Delphi [-] (http://www.clubdelphi.com/foros/#)repeat Stored := True; try DataSet.Post; except on E: EIBInterBaseError do begin // Si existe DeadLock, cambio a False Stored para repetir la inserción... Stored := not E.SQLCode = -901; if Stored then // Si Stored sigue siendo verdadero, la excepción fue otra y la relanzo... raise end end until Stored;


El código no es exactamente el mismo, pero con esto resolví el problema de los DeadLock...

Espero te sirva...


Saludos...

Gracias maeyanes, pero uso algo muy similar al tuyo con la diferencia que uso el While..do, me imagino que después del Post que tienes viene un Commit, pues se te puede presentar que al pasar el Post en ese mismo instante se apague la PC ó marque los errores tradicionales de Windows, vas a dejar bloqueado el registro hasta que le des un ShutDown a Firebird, espero nunca te suceda esto, pero en el mundo de la informatica todo puede esperarse... Gracias por tu consejo.

maeyanes
07-10-2006, 19:55:33
Bueno, si hay un TransactionStart y un Commit o Rollback en caso de otro tipo de error, pero como este código es para guardar uno o más registros en sucesión, estos van afuera del código que puse...


Saludos...

AGAG4
07-10-2006, 20:27:55
No entendí esto :confused:

pero como este código es para guardar uno o más registros en sucesión, estos van afuera del código que puse...


Donde quiera que vaya el código del Post, en alguna parte le tienes que dar el commit.
Que componentes usas????

maeyanes
07-10-2006, 20:55:22
Lo que sucede es que en realidad tengo creado un tipo de framework para trabajar con objetos en lugar de registros...

Entonces, en lugar de hacer DataSet.Post, en realidad hago algo como Objeto.Store, entonces, internamente el método mencionado hace el manejo de las transacciones...

Ahora, cuando quiero manejar inserciones masivas, vamos a decirle así, por ejemplo tipo master-detail, lo que hago es iniciar una transacción, realizar el ciclo de inserciones (Objeto.Store) y al final el Commit o Rollback dependiendo de si todo estuvo bien u ocurrió un error.

Mi código es más o menos ásí:


var
Objeto: TObjetoFrameWork;

begin
Connection.StartTransaction;
try
for I := 0 to ListaObjetos.Count - 1 do // ListaObjetos es un TList
begin
Objeto := TObjetoFrameWork(ListaObjetos[I]);
repeat
Stored := True;
try
Objeto.Store
except
on E: EIBInterBaseError do
begin
// Si existe DeadLock, cambio a False Stored para repetir la inserción...
Stored := not E.SQLCode = -901;
if Stored then // Si Stored sigue siendo verdadero, la excepción fue otra y la relanzo...
raise
end
end
until
Stored
end;
Connection.CommitTransaction
except
Connection.RollbackTransaction
end
end;


Espero que con esto te aclare mejor las cosas...



Saludos...

ronalg
10-10-2006, 02:10:10
bueno no se si te servira, yo uso generadores, pero el cliente pide un numero, y lo guardo en el registro de windows, hasta que lo necesito, una simple variable de cod_factura en el regitro, si esta variable es vacia pido un nuevo numero al generador, si esta llena uso ese valos, si hay error no vacio la variable y si no lo hay la vacio y asi garantizo que aunque se corte la luz como esta en el registro de windows puedo rescatar el número que pedí.

Espero que te sirva

AGAG4
16-10-2008, 17:54:46
Vuelvo a reabrir este hilo que hace más de 2 años lo abri, sigo con este problema de los bloqueos pesimistas, no me funciona el parametro DeadlockTimeout dentro de firebird.conf, no mata los bloqueos que duran el tiempo que especifico, lo que ha de esperar firebird es que ocurra un problema en el bloqueo pero no especifica que problemas considera para activar el DeadlockTimeout, espero a alguien haya encontrado algo para RE-matar un bloqueo muerto ....


DeadlockTimeout = Número de segundos (entero) que el gestor de bloqueos
esperará despues de la aparición de un conflicto antes de purgar todos los
bloqueos de procesos muertos y realizar un ciclo posterior de detección de
deadlocks. Normalmente el motor detecta instantáneamente los deadlocks.
El timeout de deadlocks solo se dispara cuando algo va mal.El valor
por defecto de 10 segundos es adecuado para la mayoría de las situaciones.
Configurar un valor menos no aumenta necesariamente la velocidad a la que
los deadlocks problemáticos devuelven una excepción de conflicto. Si es
demasiado bajo, el efecto puede ser escaneos extra innecesarios que
degraden el rendimiento del sistema.

RolphyReyes
16-10-2008, 18:21:39
Saludos.

No se si migraste o podrías migrar a FB >= 2.

En esta versión existe la clausula LOCK TIMEOUT.


Lock Timeout for WAIT Transactions
A. Karyakin, D. Yemanov
All Firebird versions provide two transaction wait modes: NO WAIT and WAIT. NO WAIT mode means that
lock conflicts and deadlocks are reported immediately, while WAIT performs a blocking wait which times out
only when the conflicting concurrent transaction ends by being committed or rolled back.
The new feature extends the WAIT mode by making provision to set a finite time interval to wait for the concurrent
transactions. If the timeout has passed, an error (isc_lock_timeout) is reported.
Timeout intervals are specified per transaction, using the new TPB constant isc_tpb_lock_timeout in the API or,
in DSQL, the LOCK TIMEOUT <value> clause of the SET TRANSACTION statement.


Y también:

Lock Timeout for WAIT Transactions
A. Karyakin, D. Yemanov
The new feature extends the WAIT mode by making provision to set a finite time interval to wait for the concurrent
transactions. If the timeout has passed, an error (isc_lock_timeout) is reported.
Timeout intervals can now be specified per transaction, using the new TPB constant isc_tpb_lock_timeout in
the API.
Note
The DSQL equivalent is implemented via the LOCK TIMEOUT <value> clause of the SET TRANSACTION


Un ejemplo:

SET TRANSACTION WAIT SNAPSHOT NO AUTO UNDO LOCK TIMEOUT 10


Extraído de Firebird 2.0.1 Release Notes.

Hasta luego.

AGAG4
16-10-2008, 18:33:43
Te agradezco la sugerencia, ya lo habia pensado, en este momento estoy en la version 1.5.5 tengo que hacer varios cambios en los trigger's para cambiarme a la version 2.0, cosa que estoy evaluando.... por el momento estoy investigando si en la versión 1.5.5. se puede hacer algo similar....