Вопрос

Иногда я получаю взаимоблокировки на сервере sql. Я создал функцию для блокировки операций, не связанных с базой данных (обработка кредитных карт), поэтому дублирование не может произойти. Мои функции следующие (извините за tcl, но sql достаточно ясно). Кто-нибудь может понять, почему иногда возникает тупик ?????

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]"

}
Это было полезно?

Решение

<Ол>
  • Попробуйте добавить UPDLOCK к первому выбору, чтобы принудительно установить эксклюзивную блокировку

  • Попробуйте sp_getapplock , которая предназначена для операций такого типа.

  • Я бы предпочел номер 2, лично ...

    Другие советы

    Было бы полезно иметь график взаимоблокировки.

    SQL-блокировки возникают не только из-за запросов, но также важна и схема. Например, вы можете получить взаимоблокировки Reader-Writer с совершенно действительными и исправляйте запросы просто потому, что чтение и запись выбирают разные пути доступа к данным. Я мог бы видеть, что это происходит в вашем случае, если для GranularLocks существует индекс timeActionMade, который не охватывает столбец 'object'. Но, опять же, решение будет зависеть от того, на каком фактическом тупике находится.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top