Ottenere deadlock in sqlserver
-
06-07-2019 - |
Domanda
Ricevo deadlock occasionalmente nel server sql. Ho creato una funzione per bloccare le operazioni non di database (elaborazione delle carte di credito) in modo che non possano verificarsi duplicati. Le mie funzioni sono le seguenti (scusate il tcl, ma sql è abbastanza chiaro). Qualcuno può vedere perché occasionalmente si verifica un deadlock ?????
proc ims_syn_lock_object { db object {timeout 30} {wait 1}} {
if {[catch {
while {true} {
am_dbtransaction begin $db
# read the object locks that aren't timed out
set result [am_db1cell $db "SELECT object from GranularLocks WITH (ROWLOCK,HOLDLOCK) where object = [ns_dbquotevalue $object] AND timeActionMade > DATEADD(second,-timeout, GETDATE())"]
# check to see if this object is locked and not timed out
if { [string equal "" $result] } {
break;
} else {
# another process has this object and it is not timed out.
# release the row lock
am_dbtransaction rollback $db
if { $wait } {
# sleep for between 400 and 800 miliseconds
sleep [expr [ns_rand 400] + 400]
} else {
# we aren't waiting on locked resources.
return 0;
}
}
}
# either the object lock has timed out, or the object isn't locked
# create the object lock.
ns_db dml $db "DELETE FROM GranularLocks WHERE object = [ns_dbquotevalue $object]"
ns_db dml $db "INSERT INTO GranularLocks(object,timeout) VALUES ([ns_dbquotevalue $object],[ns_dbquotevalue $timeout int])"
# releases the row lock and commits the transaction
am_dbtransaction commit $db
} errMsg]} {
ns_log Notice "Could not lock $object. $errMsg"
catch {
am_dbtransaction rollback $db
} errMsg
return 0
}
return 1
}
proc ims_syn_unlock_object {db object } {
#simply remove the objects lock
ns_db dml $db "DELETE FROM GranularLocks WHERE object = [ns_dbquotevalue $object]"
}
Soluzione
-
Prova ad aggiungere UPDLOCK alla prima selezione per forzare anche un blocco esclusivo
-
Prova
sp_getapplock
fornito per questo tipo di operazione.
Preferirei il numero 2, personalmente ...
Altri suggerimenti
Sarebbe utile avere il grafico del deadlock.
I deadlock SQL si verificano non solo a causa delle query coinvolte, ma ugualmente importante è lo schema coinvolto. Ad esempio puoi ottenere un deadlock Reader-Writer con perfettamente valido e " "corregge" semplicemente perché la lettura e la scrittura scelgono percorsi di accesso diversi ai dati. Potrei vederlo accadere nel tuo caso se esiste un indice su timeActionMade su GranularLocks che non copre la colonna "oggetto". Ma ancora una volta, la soluzione dipenderà dall'attuale deadlock.