Ver Mensaje Individual
  #1 (permalink)  
Antiguo 15/06/2009, 15:00
aquelQueTeObserva
 
Fecha de Ingreso: junio-2009
Mensajes: 2
Antigüedad: 15 años, 8 meses
Puntos: 0
Como plantear modelo asignacion elementos sin perder consistencia

Buenas tardes, ante todo mis disculpas por molestarlos con un problema que quizas
para ustedes sea trivial, espero poder plantearlo de forma clara al menos.

Para simplificarlo y dar una base digamos que tenemos que representar operarios
ingresando y extrayendo material de un deposito para ello defini 3 tablas
como siguen:
(nota: motor MySQL ver 5.1.35-community)

CREATE TABLE IF NOT EXISTS `materiales` (
`idMaterial` int(10) unsigned NOT NULL AUTO_INCREMENT,
`denominacion` varchar(50) NOT NULL,
PRIMARY KEY (`idMaterial`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

CREATE TABLE IF NOT EXISTS `operarios` (
`idOperario` int(10) unsigned NOT NULL AUTO_INCREMENT,
`nombre` varchar(50) NOT NULL,
PRIMARY KEY (`idOperario`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

CREATE TABLE IF NOT EXISTS `movimientosaterial` (
`idMovimientoMaterial` int(10) unsigned NOT NULL AUTO_INCREMENT,
`idMaterial` int(10) unsigned NOT NULL,
`idOperario` int(10) unsigned NOT NULL,
`cantidad` double NOT NULL,
PRIMARY KEY (`idMovimientoMaterial`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Con los siguientes datos iniciales para prueba:

INSERT INTO `materiales` (`idMaterial`, `denominacion`) VALUES
(1, 'hierro');

INSERT INTO `operarios` (`idOperario`, `nombre`) VALUES
(1, 'Cecilia'),
(2, 'Facundo');

INSERT INTO `movimientosaterial` (`idMovimientoMaterial`, `idMaterial`, `idOperario`, `cantidad`) VALUES
(1, 1, 1, 1000);

Donde el registro de la tabla movimientosaterial representa el estado de un material en el deposito via
una consulta como:

-- consultamos el stock de hierro <=> idMaterial = 1
SELECT SUM(cantidad) AS sumatoria FROM movimientosaterial WHERE idMaterial = 1 GROUP BY idMaterial;
-- result: sumatoria = 1000

y un movimiento sera un INSERT de cantidad positiva para indicar un ingreso o negativa para indicar una extraccion
sobre la tabla movimientosaterial.

Ahora bien, el procedimiento nomral de extraccion consistiria en los siguientes pasos

1)consultar si hay stock del material requerido
2)si el stock alcanza para satisfacer el requerimiento proceder a extraerlo

Sentado el marco de trabajo llegamos finalmente al problema, como hacer para mantener la consistencia
cuando hay concurrencia, o sea, como evitar que se le asigne a 2 operarios material por encima del disponible?

Evidentemente hay cosas que no termino de entender pues inicialmente se me ocurrio que si lo hacia usando
transacciones no habria problemas, pero descubri (usando 2 consolas en paralelo) que puedo tener una lectura
incorrecta en la segunda si esta consulta la sumatoria antes de que le de COMMIT a la primera.

Se me ocurrio entonces que quizas lo correcto seria bloquear la tabla movimientosaterial mientras ejecuto
1) y 2) impidiendo que culquier otro proceso pueda operar con ella en el intervalo en que se ejecuta
pero como nunca utilize este procedimiento tengo mis reservas sobre como se comportara en definitiva
hacer una cosa asi (debo bloquear lectura, o sea que se bloqueara cualquier proceso de lectura como los de
analisis o cualquier otra cosa que toque la tabla inluidos INNER JOINs no?)

Hay una forma mas correcta de encarar el problema?
Si la solucion es por bloqueo de tablas, asi sea de forma muy simplificada, como se haria de forma correcta
y que consecuencias tendria?

Desde ya muchas gracias por su tiempo