2009-02-27 3 views
7

Sei a conoscenza di uno strumento ORM che offre il recupero dei deadlock? So che i deadlock sono una brutta cosa, ma a volte qualsiasi sistema ne risentirà, data la giusta quantità di carico. In Sql Server, il messaggio di deadlock dice "Rieseguire la transazione", quindi sospetto che il rilancio di un'istruzione deadlock sia una funzionalità desiderabile su ORM.Supporto ORM per la gestione dei deadlock

+0

I Non uso gli ORM, ma sono sorpreso che questa non sia una caratteristica vitale della maggior parte delle ORM! Grazie per una domanda illuminante –

+0

Ho codificato uno per me stesso in Python, ma funziona con query SQL raw. La ragione per la quale la maggior parte dei framework ORM non lo supporta è che il design API in uso comune non lo supporta. L'ORM non ha il pieno controllo della transazione, quindi non può realmente eseguire nuovamente le transazioni fallite. –

risposta

3

Non conosco alcun supporto speciale di strumenti ORM per rieseguire automaticamente le transazioni non riuscite a causa di deadlock. Tuttavia, non penso che un ORM faccia molto diversamente i problemi di blocco/deadlocking. In primo luogo, dovresti analizzare la causa principale dei tuoi deadlock, quindi riprogettare le tue transazioni e le tue query in modo da evitare o almeno ridurre i deadlock. Ci sono molte opzioni di miglioramento, come la scelta del giusto livello di isolamento per (parti) delle tue transazioni, l'uso di lock hint ecc. Questo dipende molto più dal tuo sistema di database che dal tuo ORM. Naturalmente aiuta se il tuo ORM ti permette di usare stored procedure per alcuni comandi di precisione etc.

Se questo non aiuta a evitare completamente le deadlock, o non hai il tempo di implementare e testare il vero Correggere ora, ovviamente si potrebbe semplicemente mettere un tentativo/aggirare il salvataggio/commit/persist o qualsiasi altra chiamata, controllare le eccezioni rilevate se indicano che la transazione fallita è una "vittima deadlock", e quindi semplicemente richiamare save/commit/persist dopo pochi secondi di sonno. Attendere qualche secondo è una buona idea poiché le deadlock sono spesso un'indicazione che c'è un picco temporaneo di transazioni in competizione per le stesse risorse, e ripetere la stessa transazione rapidamente ancora e ancora probabilmente renderebbe le cose ancora peggiori.

Per lo stesso motivo, probabilmente non si sarà sicuri di provare solo una volta per eseguire nuovamente la stessa transazione.

In uno scenario del mondo reale, una volta implementato questo tipo di soluzione alternativa, circa l'80% delle "vittime di stallo" è riuscito al secondo tentativo. Ma consiglio vivamente di scavare più a fondo per risolvere il vero motivo del deadlock, perché questi problemi di solito aumentano in modo esponenziale con il numero di utenti. Spero possa aiutare.

+0

Buoni punti, grazie. Tuttavia, se sappiamo che si verificano deadlock e che esistono strategie per gestirli (almeno con Sql Server), perché non inserirli nel DAL? Non dovrebbe essere auspicabile in un ORM? –

+1

Penso che sia ancora una soluzione alternativa e il supporto di prima classe per tale soluzione alternativa incoraggerebbe le persone a stare con una pseudo soluzione invece di risolvere il problema reale. – realMarkusSchmidt

1

I deadlock sono prevedibili e SQL Server sembra essere peggio di fronte agli altri server di database. Per prima cosa, dovresti cercare di minimizzare i tuoi deadlock. Prova a utilizzare lo SQL Server Profiler per capire perché è successo e cosa puoi fare al riguardo. Quindi, configurare l'ORM in modo che non venga letto dopo aver eseguito un aggiornamento nella stessa transazione, se possibile. Infine, dopo averlo fatto, se usi Spring e Hibernate insieme, puoi mettere un intercettore per controllare questa situazione. Estendi MethodInterceptor e posizionalo nel bean Spring sotto interceptorNames. Quando viene eseguito l'intercettatore, utilizzare invocation.proceed() per eseguire la transazione. Catch eventuali eccezioni e definire un numero di volte che si desidera riprovare.

+0

Sapete se Hibernate è in grado di tenere traccia delle dichiarazioni in una transazione e rieseguire tutte in caso di deadlock? Tale caratteristica sarebbe auspicabile in un ORM? –

+0

"SQL Server sembra essere peggio di questo fronte rispetto ad altri server di database" - completamente falso. Forse uno dei motivi per cui qualcuno potrebbe pensarlo, è che è così facile iniziare a usare SQL Server, è anche facile commettere errori. –

+0

Penso davvero che SQL faccia un buon lavoro, considerando alcuni degli schemi di database horror che ho visto nel corso degli anni. – RobS

0

Un sistema che ho lavorato è stato sulla base di “comandi” che poi sono stati commessi al database quando l'utente preme Salva, ha funzionato in questo modo:

While(true) 
    start a database transaction 
    Foreach command to process 
     read data the command need into objects 
     update the object by calling the command.run method 
    EndForeach 
    Save the objects to the database 
    If not deadlock 
    commit the database transaction 
    we are done 
    Else 
    abort the database transaction 
    log deadlock and try again 
    EndIf 
EndWhile 

Si può essere in grado di fare qualcosa di simile con qualsiasi ORM; abbiamo usato un sistema di accesso ai dati interno, in quanto gli ORM erano troppo nuovi al momento.

Eseguiamo i comandi all'esterno di una transazione mentre l'utente interagiva con il sistema. Quindi rieseguili come sopra (quando usi "salva") per far fronte alle modifiche che altre persone hanno fatto. Dato che avevamo già un buon ideale delle righe, il comando sarebbe cambiato, potremmo anche utilizzare i suggerimenti di blocco o "selezionare per l'aggiornamento" per rimuovere tutti i blocchi di scrittura necessari all'inizio della transazione.(Abbiamo interrotto il set di righe da aggiornare per ridurre ulteriormente il numero di deadlock)

+0

Grazie. Quindi si potrebbe ritenere accettabile che un ORM offra tale funzione, anche se alcuni altri intervistati sono contrari all'idea perché potrebbero portare a una mancanza di attenzione da parte degli sviluppatori? –

+0

Penso che debba essere costruito sopra l'ORM, poiché non tutte le applicazioni utilizzano i comandi. Un ORM non sa come rieseguire il codice C# dopo tutto. –

+0

Potrebbe sapere se ad esempio quando si avvia una transazione si raccolgono ciascuna istruzione in entrata come un'unità di lavoro e la si riproduce in caso di un errore come deadlock. –

0

Un mappatore di o/r non è in grado di rilevare ciò, poiché il deadlock si verifica sempre all'interno del DBMS, che potrebbe essere causato da blocchi impostato da altri thread o altre app anche.

Per essere sicuri che una parte di codice non crei un deadlock, utilizzare sempre queste regole: - eseguire il recupero al di fuori della transazione. Quindi, prima recuperare, quindi eseguire l'elaborazione quindi eseguire istruzioni DML come inserire, eliminare e aggiornare - ogni azione all'interno di un metodo o una serie di metodi che contengono/funzionano con una transazione devono utilizzare la stessa connessione al database. Questo è necessario perché, ad esempio, i blocchi di scrittura vengono ignorati dalle istruzioni eseguite sulla stessa connessione (poiché la stessa connessione imposta i blocchi;)).

Spesso i deadlock si verificano perché il codice recupera i dati all'interno di una transazione che provoca l'apertura di una nuova connessione (che deve attendere i blocchi) o utilizza connessioni diverse per le istruzioni di una transazione.

+0

Il mio scopo era un po 'meno ambizioso della totale sicurezza che i deadlock sarebbero stati evitati o gestiti in tutte le situazioni. Il fatto è che ho visto casi in cui si verificano deadlock a causa del caricamento e riprovare a eseguire le istruzioni è la cosa giusta da fare (principalmente SQL Server si comporta in questo modo). –

+0

Bene, le cose che dovresti fare sono: 1) assicurati che ogni operazione in un thread dopo l'avvio di una transazione avvenga con la stessa connessione e 2) se si verifica un'eccezione, dovresti riprovare ogni operazione poiché la transazione completa non è riuscita e corso 3) vai fuori dalla transazione! –

+0

In molti casi, il blocco eccessivo o il deadlocking possono essere alleviati o eliminati creando gli indici "giusti" per il carico di lavoro delle query. –

0

Ho avuto una rapida occhiata (senza dubbio lo avete anche voi) e non ho trovato nulla che suggerisse che l'ibernazione lo offra almeno. Questo probabilmente perché gli ORM lo considerano al di fuori dell'ambito del problema che stanno cercando di risolvere.

Se si verificano problemi con deadlock, seguire alcuni dei suggerimenti postati qui per cercare di risolverli. Dopodiché devi solo assicurarti che tutto il codice di accesso al tuo database venga avvolto con qualcosa che possa rilevare un deadlock e riprovare la transazione.