2015-05-15 23 views
5

Ho questo strano problema nella mia applicazione. Succede davvero raramente come una volta o può essere due volte in una settimana. Quindi, fondamentalmente, ecco la situazione:Transazione server Sql Timeout impegno

Ho questo metodo nella mia applicazione che interroga DB più volte, prima ci sono 4 selezioni, una di esse usa la parola chiave UPDLOCK quindi segue un inserimento nell'altra tabella (non una a cui viene applicato il UPDLOCK) e l'aggiornamento sulla tabella che era precedentemente UPDLOCK -ed.

Tutte queste query vengono eseguite in un'unica transazione (che è al lato di .NET) e infine riceve COMMIT -ed.

Ora, il problema è che il transaction.Commit() tiri eccezione con il messaggio

Timeout scaduto. Il periodo di timeout è scaduto prima del completamento dell'operazione o il server non risponde

(come suppongo che SqlConnection volte out).

così ho tutta questa procedura avvolto in un blocco try-catch e se si verifica un'eccezione cerco di rollback della transazione in modo che quando questo accade l'esecuzione del codice va a catch blocco ed transaction.RollBack() si chiama e getta anche un'eccezione con il messaggio

Questo SqlTransaction è stato completato. essa non è più utilizzabile

(come immagino che quando i COMMIT volte l'operazione in realtà ottiene COMMIT -ed), quindi dopo questo alcune parti della domanda scombina. La cosa che si ritiene non esista (a causa di ROLLBACK) esiste effettivamente e causa alcuni problemi imprevisti che vengono quindi risolti manualmente (in questo momento).

Non sono riuscito a trovare nulla che potesse indicare quale fosse il problema, piuttosto che aumentare il timeout di SqlConnection. Se qualcuno ha già affrontato questo problema, potresti condividere l'esperienza, grazie in anticipo. (L'utilizzo della CPU del server DB non va mai al di sopra 45-50%, è la maggior parte dei casi si gira a vuoto al 3-15%)

Ecco la prima selezione SQL --First Selezionare

SELECT TOP 1 
      t.Id , 
      t.OId , 
      t.Amount , 
    t.DUserId, 
      t.StartDate , 
      t.ExtDesc, 
    t.StatusId 
    FROM dbo.[Transaction] t 
      JOIN dbo.Wallet cw ON t.CId = cw.Id 
      JOIN dbo.Wallet dw ON t.DId = dw.Id 
    WHERE ExtKey = @ExtKey 
      AND (cw.vId = @vId 
        OR dw.VId = @vId 
       ) 

--Second Selct which executes twice with differenc params 


    SELECT u.Id , 
      UserName , 
      PinCode , 
      CurrencyId , 
      StatusId , 
      PersonalNumber , 
      gu.DefaultVendorServiceId , 
      CountryId, 
    u.FirstName, 
    u.LastName 
    FROM dbo.[User] u 
      LEFT JOIN dbo.GamblerUser gu ON gu.UserId = u.Id 
    WHERE u.Id = @UserId 


--Last select with (updlock) 


SELECT w.Id, AccountNo, FundTypeId, VendorServiceId, Balance, UserId, vs.IsLocalAccount 

FROM Wallet w (UPDLOCK) 
JOIN VendorService vs on w.VId = vs.Id 
WHERE 
    w.UserId = @UserId 
AND w.FundTypeId = @FundTypeId 
AND w.VendorServiceId = @VendorServiceId 


-- Insert 


    INSERT INTO [dbo].[Transaction] 
      (StartDate , 
       OTypeId , 
       StatusId , 
       Amount , 
       ExtDesc, 
       DUserId 
      ) 
    VALUES     (@StartDate , 
       @OTypeId , 
       @StatusId , 
       @Amount , 
       @ExtDesc, 
       @DUserId 
      ) 

    SET @Id = (SELECT @@IDENTITY 
      ) 


-- Update on updlocked table  


UPDATE dbo.Wallet SET 

    Balance = ISNULL(@Balance, Balance) 

WHERE Id = @Id 
+0

@MitchWheat Sql o C#? – Dimitri

+1

Contrariamente alla credenza popolare, gli utenti SO non sono psichici e non sono in grado di eseguire un progetto astrale davanti al computer per vedere il codice. Sarebbe fantastico se potessi pubblicare uno snippet di codice. Ti auguro ogni bene – MickyD

+0

Ho aggiunto il codice – Dimitri

risposta

3

(presumo questo non è Hekaton che fa la cosa in modo diverso su commit.)

Un commit di solito richiede una quantità insignificante di tempo. Una scrittura fisica deve essere inviata al registro e, nel caso di Mirroring/AG, è necessario effettuare un viaggio di andata e ritorno in rete. Una di queste cose potrebbe contenere il commit qui.

Personalmente ho riscontrato questo problema con una connessione Mirroring sovraccaricata.

Il timeout di commit non può essere modificato separatamente (che considero un difetto). È in uso il timeout di connessione.

Analizzare le cause principali che ho menzionato sopra. Come soluzione alternativa aumentare il timeout di commit.

In caso di commit non riuscito non è possibile presumere che la transazione sia stata effettivamente commessa o meno. (Questo è il problema dei due generali. In generale è irrisolvibile.) È necessario escogitare un tipo di controllo per verificare se il database contiene o meno le scritture previste. Questo è più comune su Azure. Consulta la guida di Azure.

+0

grazie. c'era qualche problema con la rete (il database è specchiato) – Dimitri

Problemi correlati