Ho un programma che si collega a un database Oracle ed esegue operazioni su di esso. Ora voglio adattare quel programma per supportare anche un database SQL Server.In SQL Server, come posso bloccare una singola riga in modo simile a "SELECT FOR UPDATE WAIT" di Oracle?
Nella versione Oracle, utilizzo "SELECT FOR UPDATE WAIT" per bloccare le righe specifiche di cui ho bisogno. Lo uso in situazioni in cui l'aggiornamento è basato sul risultato di SELECT e altre sessioni non possono assolutamente modificarlo contemporaneamente, quindi devono prima bloccarlo manualmente. Il sistema è altamente soggetto a sessioni che tentano di accedere agli stessi dati nello stesso momento.
Ad esempio:
Due utenti tentano di recuperare la riga nel database con la priorità più alta, contrassegnarla come occupata, eseguire operazioni su di essa e contrassegnarla come disponibile di nuovo per un utilizzo successivo. In Oracle, la logica sarebbe andato sostanzialmente in questo modo:
BEGIN TRANSACTION;
SELECT ITEM_ID FROM TABLE_ITEM WHERE ITEM_PRIORITY > 10 AND ITEM_CATEGORY = 'CT1'
ITEM_STATUS = 'available' AND ROWNUM = 1 FOR UPDATE WAIT 5;
UPDATE [locked item_id] SET ITEM_STATUS = 'unavailable';
COMMIT TRANSACTION;
Nota che le query sono costruite in modo dinamico nel mio codice. Si noti inoltre che quando la riga precedentemente più favorevole è contrassegnata come non disponibile, il secondo utente passerà automaticamente a quello successivo e così via. Inoltre, utenti diversi che lavorano su diverse categorie non dovranno aspettare che i blocchi di ciascuno vengano rilasciati. Il peggiore peggiore, dopo 5 secondi, verrà restituito un errore e l'operazione verrà annullata.
Quindi, infine, la domanda è: come ottengo gli stessi risultati in SQL Server? Ho guardato i suggerimenti di blocco che, in teoria, sembrano come dovrebbero funzionare. Tuttavia, gli unici blocchi che impediscono altri blocchi sono "UPDLOCK" E "XLOCK" che funzionano entrambi a livello di tabella.
Questi suggerimenti di blocco che funzionano a livello di riga sono tutti blocchi condivisi, che inoltre non soddisfano le mie esigenze (entrambi gli utenti possono bloccare la stessa riga allo stesso tempo, contrassegnarli come non disponibili ed eseguire operazioni ridondanti sull'elemento corrispondente).
Alcune persone sembrano aggiungere una colonna "tempo modificato" in modo che le sessioni possano verificare che siano quelle che l'hanno modificata, ma sembra che ci siano molti accessi ridondanti e non necessari.
E 'bene sapere, ma sembra che Serializable impedirà legge solo se i dati sono stati modificati, in modo da non impedire che le serrature fino a quel momento. – Paradoxyde
@Paradoxyde: non è la mia comprensione. Per la seconda voce della specifica (vedi la mia modifica sopra) la riga viene bloccata non appena viene letta fino alla fine della transazione. Da quale parte della specifica hai ricevuto la tua domanda? –
Questo acquisisce un blocco condiviso e in seguito un blocco esclusivo, quindi è vulnerabile a deadlock – Andomar