2012-06-30 21 views
7

Ho un sito Web in cui gli utenti possono acquistare i biglietti, ma le quantità dei biglietti sono generalmente limitate e vanno rapidamente. Sto cercando di implementare un sistema di deposito a garanzia in modo che un utente possa fare clic su quel numero di ticket x, a quel punto li inserirò in uno stato di deposito a garanzia. Questo dà loro diversi minuti per inserire i dati della carta di credito e completare l'acquisto.Operazioni atomiche MySQL e blocco tabella

Ho tre tabelle pertinenti: eventi, ticket e impegno. Una riga nella tabella degli eventi descrive l'evento stesso, incluso il numero massimo di biglietti disponibili.

La tabella biglietti detiene il seguente:

user_id: l'utente che ha acquistato i biglietti

number_of_tickets: quanti biglietti hanno acquistato

event_id: l'evento rilevante

Il piano di deposito di garanzia contiene quanto segue:

user_id: l'utente nel processo di acquisto dei biglietti

number_of_tickets: quanti biglietti che vogliono

event_id: l'evento rilevante

Attualmente, lo faccio tre MySQL domande, una per i ticket massimi, una per il numero di biglietti venduti e una per il numero di biglietti già in deposito. Poi ho calcolato:

$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."; 
} 

mio problema è che è possibile per più di un utente per essere eseguito il codice, allo stesso tempo. Se un utente dovesse chiamare beginEscrowdopo il, un altro utente aveva già letto il numero di biglietti già in deposito, è possibile che io sovrastimerò lo spettacolo.

Sto utilizzando il motore InnoDB per i miei tavoli e ho letto come bloccare una singola riga utilizzando SELECT .... FOR UPDATE, ma non sto aggiornando una singola riga. La funzione beginEscrow inserirà semplicemente una nuova riga nella tabella di deposito. Calcolo $tickets_in_escrow leggendo tutte le righe con l'ID evento corretto e sommando il numero di ticket in ognuno di essi.

Forse sto sbagliando tutto?

Devo bloccare l'intero tavolo?

Non posso essere il primo a scrivere un sistema di deposito di biglietti. Mi sono suicidato cercando di trovare qualche tutorial su questo genere di cose, ma ho suonato. Qualsiasi idea sarebbe utile.

Grazie!

risposta

9

Sei molto vicino al tuo progetto, ma non proprio lì.

Prima di tutto, la vostra tabella degli eventi deve contenere il numero di biglietti ancora disponibili per il vostro evento (in aggiunta a qualsiasi altra cosa che vuoi lì).

In secondo luogo, la tabella di deposito deve avere una colonna DATETIME che indica quando scade l'impegno. È necessario impostare tale valore ogni volta che i biglietti entrano in deposito.

In terzo luogo, l'operazione di mettere i biglietti in escrow ha bisogno di

  1. bloccare la fila evento.
  2. leggere la colonna dei biglietti disponibili. (interrompi se non sono disponibili abbastanza)
  3. inserisci una riga nella tabella di deposito
  4. aggiorna la riga di evento per decrementare la colonna di ticket disponibile.
  5. sblocca la riga dell'evento.

In quarto luogo, l'azione di completamento della vendita deve eliminare la riga di deposito a garanzia e inserire una riga di biglietti venduti. Questo non è difficile.

In quinto luogo, è necessaria un'operazione di pulizia di escrow. Ciò deve cercare tutte le righe di escrow scadute (che hanno una data di scadenza nel passato) e, per ognuna:

  1. bloccare la riga di evento corrispondente.
  2. leggere il numero di ticket con impegno dalla tabella di deposito
  3. eliminare la riga della tabella di deposito.
  4. aggiornare la riga di evento per incrementare la colonna di ticket disponibili.
  5. sblocca la riga dell'evento.

Il trucco è quello di avere il numero di disponibili biglietti mantenuti in un modo che è asservito in modo corretto, quindi le condizioni di gara tra gli utenti non oversell il vostro evento.

+0

Quindi, in altre parole, tutto il conteggio ticket di deposito deve essere in una singola riga in una singola tabella, piuttosto che una somma delle righe nella tabella di deposito. Capisco come abbia senso. Grazie. – user1493634

+0

In realtà, tutto il conteggio dei ticket, disponibile, depositato e venduto, dovrebbe trovarsi in una singola colonna di una singola riga in una singola tabella. Quella colonna colpisce zero, non ci sono più posti da vendere. Ma tu hai l'idea. –

+0

In StackOverflow, se una risposta ti aiuta devi accettarlo facendo clic sul segno di spunta verde. –

Problemi correlati