Re: Bloqueo en registro-tabla

From: suso <jlcubas(at)terra(dot)es>
To: Jaime Casanova <jcasanov(at)systemguards(dot)com(dot)ec>
Cc: Mariano Reingart <mariano(at)nsis(dot)com(dot)ar>, pgsql-es-ayuda(at)postgresql(dot)org
Subject: Re: Bloqueo en registro-tabla
Date: 2009-06-16 11:44:36
Message-ID: 4A3785A4.8040000@terra.es
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Hola Jaime, estoy de acuerdo en algunos puntos, coo por ejmplo si el
medico se va a los pocos minutos,en este caso se supone que ha salido
del programa normalmente (no apagando el pc directamente), aqui se
desbloquea, ahora, si apaga directamente el pc(porque se quede bloqueado
por ejemplo), si lo enciende de nuevo(reinicia) y entra en el programa,
no habria problema(por su ip).
En cuanto al tiempo, te puedo comentar, que en determinados casos(casos
nuevos y cosas así), si puede llegar a ese tiempo,quizás no 90', pero si
muy fácil los 60', es muy dificil que 2 personas, llámese médicos, data
manager, etc, habran para modificar datos, ya que un paciente no puede
estar en 2 sitios a la vez, pero si para modificar y otro/s médico/s
para consulta(en este caso sin problemas)
Que es un tremendo lío, pues sí, y cuanto más me comentáis al respecto,
mas me doy cuenta:(
El bloqueo que yo había diseñado (y lo tengo en pruebas en mi red) es:

El médico entra en ese paciente,mira una tabla (especial para eso), si
no está bloqueada,la bloquea, cualquier otro medico que entre a ese
paciente, hace lo mismo, mira, si está bloqueada, si lo está, se le
avisa de que sólo puede leer, cada vez que intente guardar algún dato de
las diferentes pantallas, pasa lo mismo, mira, si está bloqueado o no, y
cuadno el medico o bien cambie de paciente o cierre el programa, se
libera el, blqoueo

> 2009/6/15 Mariano Reingart <mariano(at)nsis(dot)com(dot)ar>:
>> Al empezar, haces:
>> SELECT *, xmin FROM historia_clinica WHERE numero=1234;
>> -- guardas el xmin y empieza la edición (por ej, en variable xmin0)
>>
>> -- al guardar, comienzo una transacción
>> BEGIN;
>> -- selecciono el xmin actual y bloqueo la tabla para que otro no pueda
>> modificar ese registro
>> SELECT xmin FROM historia_clinica WHERE numero=1234 FOR UPDATE;
>> -- si xmin != xmin0 lanzar un error porque los datos se modificaron
>> (ROLLBACK)
>> -- si xmin == xmin0, hacer el UPDATE y COMMIT
>>
> [...]
>> BEGIN;
>> SELECT fecha_bloqueo+CAST('24 hours' AS INTERVAL)<now() AS bloqueado FROM
>> historia_clinica WHERE numero=1234 FOR UPDATE;
>> -- si bloqueado es TRUE, todavia no paso el periodo de 24hs), hacer ROLLBACK
>> e informar al usuario que el registro esta bloqueado.
>> -- si bloqueado es NULL o falso (por ej., pasaron 24hs), pones una nueva
>> fecha de bloqueo (que comienza ahora):
>> UPDATE historia_clinica SET fecha_bloqueo=now() WHERE numero=1234;
>> COMMIT;
>>
>
> para que usas el xmin en este enredo?
> solo necesitas grabar la fecha y al menos el usuario (y quizá la ip de
> la máquina cliente)
>
> -- esta transaccion es obviamente pseudocodigo...
> BEGIN;
> SELECT * FROM historia_clinica WHERE numero=1234 FOR UPDATE NO WAIT;
> -- si no se puede bloquear alguien lo tiene bloqueado, ROLLBACK
> -- probablemente puedes agregar la condición del IF en el SELECT
> IF historia_clinica.fecha_bloqueo IS NULL OR
> historia_clinica.usuario_bloqueo = current_user THEN
> UPDATE historia_clinica SET fecha_bloqueo = now(), usuario_bloqueo
> = current_user
> WHERE numero = 1234;
> END IF;
> COMMIT;
>
> crea un trigger en la tabla historia_clinica que sea mas o menos asi:
>
> CREATE FUNCTION verifica_bloqueo() RETURNS TRIGGER AS $$
> BEGIN
> IF old.fecha_bloqueo IS NULL THEN
> RETURN NEW;
> END IF;
>
> IF old.usuario_bloqueo = current_user THEN
> -- yo mismo lo habia bloqueado, asi que puedo continuar
> RETURN NEW;
> END IF;
>
> -- si lo tenia bloqueado alguien mas, chequeo cuando lo
> bloqueo para saber si puedo ignorar ese bloqueo.
> -- ojo que now() usa la fecha de inicio de la transaccion,
> otras opciones en
> -- http://www.postgresql.org/docs/8.3/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT
> IF old.fecha_bloqueo + CAST('90 minutes' AS INTERVAL) < now() THEN
> RETURN NEW;
> END IF;
> RAISE EXCEPTION 'registro bloqueado.'
> RETURN NULL;
> END;
> LANGUAGE plpgsql;
>
> -- la razon por la que lo creo con el 1 adelante es para que se
> ejecute primero (los triggers se ejecutan en orden alfabético,
> -- me parece que el 1 esta antes de las letras) para que no pierda el
> tiempo haciendo otras verificaciones que podrian
> -- no servir si el registro estaba bloqueado
> CREATE TRIGGER 1_trg_verifica_bloqueo BEFORE UPDATE ON historia_clinica
> FOR EACH ROW EXECUTE PROCEDURE verifica_bloqueo();
>
> ahora si desconectate todo lo que quieras... el FOR UPDATE evitara que
> dos usuarios bloqueen logicamente el mismo registro a la vez y el NO
> WAIT es para que de un error si alguien ya tenia un bloqueo físico en
> el registro en lugar de simplemente esperar al COMMIT, y luego el
> trigger se asegurara que nadie modifique un registro bloqueado
> lógicamente
>
> vaya complicación!!!
> cuéntame que vas a hacer el día que un medico deje bloqueado un
> registro y una vez que el se vaya a su casa (10 minutos después) otro
> medico necesite modificar ese registro pero como esta bloqueado le
> tocara esperar 80 minutos!!! (y claro como con todo usuario necesita
> modificarlo de urgencia, no puede esperar 80 minutos, ni 10 ni nada)
>
>> Obviamente cuando el usuario modifica definitivamente el registro, tenes que
>> establecer la fecha de bloqueo a NULL para liberar el registro,
>
> y el usuario_bloqueo claro
>
>> Se podría ir más lejos con triggers para evitar que otro usuario no pueda
>> escribir en el mismo registro (haciendo un bloqueo "más físico" y no tan
>> lógico), pero esto ya sería mucho más complejo.
>>
>
> en realidad me parece mas simple...
>
> ahora, insisto en que es demasiada complicación solo por el capricho
> de quererse desconectar sin aun saber si vas a tener algún problema
> realmente manteniendo la conexión durante toda la transacción.
> y creeme 90 minutos es un tiempo exagerado, posiblemente lo escogieron
> de forma arbitraria.
>

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Javier Chávez B. 2009-06-16 11:51:57 Re: Bloqueo en registro-tabla
Previous Message Dilm E.I.R.L 2009-06-16 05:00:15 Re: Backup