Tengo un sitio web donde los usuarios pueden comprar boletos, pero las cantidades de boletos suelen ser limitadas y van rápidamente. Estoy tratando de implementar un sistema de depósito en garantía de manera que un usuario pueda hacer clic en que quiere x número de boletos, y en ese momento los pondré en un estado de depósito en garantía. Eso les da varios minutos para ingresar la información de su tarjeta de crédito y completar la compra.Operaciones atómicas MySQL y bloqueo de tabla
Tengo tres tablas relevantes: eventos, boletos y fideicomiso. Una fila en la tabla de eventos describe el evento en sí, incluida la cantidad máxima de tickets disponibles.
La mesa de entradas sostiene lo siguiente:
user_id: el usuario que compró las entradas
number_of_tickets: ¿cuántos billetes se compran
event_id: el evento relevante
La tabla de depósito en garantía contiene lo siguiente:
user_id: el usuario en el proceso de compra de billetes
number_of_tickets: cuántas entradas que quieren
event_id: el evento relevante
Actualmente, hago tres MySQL consultas, una para las entradas máximas, una para el número de boletos vendidos y una para el número de boletos que ya están en custodia. Entonces calculo:
$remaining_tickets = $max_tickets - $tickets_sold - $tickets_in_escrow;
if ($remaining_tickets >= $tickets_desired)
{
beginEscrow($user_id, $event_id, $tickets_desired);
}
else
{
echo "Error: not enough ticket remain.";
}
Mi problema es que es posible que más de un usuario a ser la ejecución de este código a la vez. Si un usuario fuera a llamar al beginEscrow
después de otro usuario ya había leído el número de boletos que ya estaban en custodia, es posible que venda el programa en exceso.
Estoy usando el motor InnoDB para mis tablas, y he leído cómo bloquear una sola fila usando SELECT .... FOR UPDATE
, pero no estoy actualizando una sola fila. La función beginEscrow
simplemente insertará una nueva fila en la tabla de custodia. Calculo $tickets_in_escrow
leyendo todas las filas con la identificación de evento correcta y sumando el número de tickets en cada una de ellas.
Tal vez estoy haciendo todo mal?
¿Debo bloquear toda la tabla?
No puedo ser el primero en escribir un sistema de fideicomiso de boletos. Me busqué en la red tratando de encontrar algún tutorial sobre este tipo de cosas, pero me pongo nervioso. Cualquier idea sería útil.
Gracias!
Por lo tanto, en otras palabras, todo el conteo de los tickets en custodia debe estar en una sola fila en una sola tabla, en lugar de una suma de las filas en la tabla de custodia. Veo cómo eso tiene sentido. Gracias. – user1493634
En realidad, todo el conteo de boletos, disponible, en depósito y vendido, debe estar en una sola columna de una sola fila en una sola tabla. Esa columna llega a cero, no hay más asientos para vender. Pero tienes la idea. –
En StackOverflow, si una respuesta lo ayuda, debe aceptarlo haciendo clic en la marca de verificación verde. –