Penso che la soluzione sia valida in generale. È un esempio di blocco pessimistico e inestimabile se si desidera risparmiare risorse o elaborare dati con contesa elevata.
Nel tuo caso, poiché lo scopo di questi operatori è esclusivamente quello di elaborare le richieste dei tuoi clienti, sembra probabile una contesa. Quindi, stai bloccando il record assicurandoti che non venga visualizzato nelle query di altri operatori. Cioè, puoi distinguere i record bloccati e "disponibili" usando il tuo campo lock_status
.
IMO manca una cosa. Questo è chiaramente un record memorizzato in un database (ad esempio, non si rimuovono richieste da una coda o alcun bus di messaggi interni, ad esempio JMS, MQ). Pertanto, si desidera assicurarsi che il record bloccato non sia stato bloccato durante il tempo in cui è stato acquisito (problema di aggiornamento perso).
Quindi, raccomanderei un ulteriore campo "lock" che è effettivamente un blocco sul record. Questo per garantire che solo tu abbia bloccato il record in anticipo. Solitamente questo sarebbe chiamato semplicemente sulla falsariga di "lock" o "version" ma per evitare confusione con lock_status
lo chiamerò "record_lock".
Quando esegui una query su customer_query
, includi record_lock
nella query. Quindi, quando esegui l'aggiornamento per aggiornare lock_status
e lock_time
il tuo aggiornamento dovrebbe includere anche una nuova clausola where where record_lock = /*the value retrieved during your query*/
Questo garantisce che tu sia l'unico operatore che aggiorna quel record e che non è cambiato da quando hai letto. Come sai che non è cambiato? La clausola where stabilisce che record_lock
è uguale a quando lo hai interrogato. Cosa lo avrebbe cambiato? Tu! Quando esegui l'aggiornamento di cui sopra, dovresti includere anche un aggiornamento di record_lock
in un nuovo valore (sequenza, record-hash, data / ora derivata? Dipende da te).
Per riepilogare, leggi record_lock
sulla tua query e assicurati che non sia cambiato quando aggiorni (la clausola where). Includi l'aggiornamento alla record_lock
nell'aggiornamento stesso per indicare che l'hai modificato, quindi invalida chiunque altro cerchi di bloccare questo record. Una volta bloccato, dovrebbe essere tuo per lavorare con la fornitura di questi record tutti rispettano il tuo locked_status
per interrogare.
Esempio:
select request_id, lock_status, lock_time, record_lock
from customer_request
where lock_status = 0;
...
update customer_request
set lock_status = 1,
lock_time = ...,
record_lock = <somenewvalue>
where request_id = <requestid>
and record_lock = <originalrecordlock>;
Implicazioni:
- Il blocco pessimistico richiede un sovraccarico nella gestione del blocco.
- Esiste il rischio di deadlock se si richiede l'acquisizione di più blocchi.
- tre è il rischio che un record non venga elaborato e indirizzato con la soglia di timeout.
Note:
- Lo chiamerei solo "stato" se si tratta di un vero e proprio campo di stato. Se è solo un binario vero / falso, basta chiamarlo "bloccato", "locked_flag", "is_locked" o qualsiasi altra cosa secondo i tuoi standard.
- Interessante a parte ... Quando aggiorniamo lock_status, questo aggiornamento utilizza il blocco ottimistico (utilizzando un campo di blocco record). Quando elabori il customer_request, utilizziamo il blocco pessimistico (abbiamo bloccato il record in anticipo).