sql >> Databasteknik >  >> RDS >> Sqlserver

Får ibland SqlException:Timeout har gått ut

Du måste undersöka detta på serversidan för att förstå varför körningen tar slut. Observera att servern inte har någon timeout, timeouten orsakas av standardinställningen 30 sekunder på SqlCommand.CommandTimeout .

En bra resurs är Väntor och köer , som är en metod för att diagnostisera prestandaflaskhalsar med SQL Server. Baserat på den faktiska orsaken till timeouten kan lämpliga åtgärder vidtas. Du måste först och främst fastställa om du har att göra med långsam exekvering (en dålig plan) eller blockering.

Om jag skulle våga mig på en gissning skulle jag säga att det ohälsosamma mönstret IF EXISTS... UPDATE är grundorsaken. Detta mönster är felaktigt och kommer att orsaka fel under samtidighet. Två samtidiga transaktioner som exekverar IF EXISTS samtidigt kommer båda att nå samma slutsats och båda försök att INSERT eller UPDATE . Beroende på de utgående begränsningarna i databasen kan du hamna i ett dödläge (det lyckliga fallet) eller med en förlorad skrivning (det oturliga fallet). Men bara ordentlig undersökning skulle avslöja den faktiska grundorsaken. Kan vara något helt annat, som händelser för automatisk tillväxt .

Din procedur hanterar också CATCH-blocket felaktigt. Du måste alltid kontrollera XACT_STATE() eftersom transaktionen redan kan återställas när ditt CATCH-block körs. Det är inte heller klart vad du förväntar dig av att namnge transaktionen, detta är ett vanligt misstag som jag ofta ser förknippas med att förväxla namngivna transaktioner med räddningspunkter. För ett korrekt mönster se Undantagshantering och kapslade transaktioner a> .

Redigera

Här är ett möjligt sätt att undersöka detta:

  1. Ändra relevant CommandTimeout till 0 (dvs. oändlig).
  2. Aktivera blocked process threshold , ställ in den på 30 sekunder (fd CommandTimeout)
  3. Övervaka i Profiler för Rapporthändelse för blockerad process
  4. Starta din arbetsbelastning
  5. Se om Profiler producerar några rapporthändelser. Om det gör det kommer de att hitta orsaken.

Dessa åtgärder kommer att orsaka en "blockerad processrapport"-händelse varje gång du skulle få en timeout, om timeouten orsakades av blockering. Din ansökan kommer att fortsätta att vänta tills blockeringen har tagits bort, om blockeringen orsakas av en live-lock då kommer det att vänta för evigt.



  1. efterföljande nollor går inte in i databasen

  2. Hur man skriver en MySQL-fråga som returnerar en tillfällig kolumn som innehåller flaggor för huruvida ett objekt relaterat till den raden finns i en annan tabell eller inte

  3. MySQL-tabellnamn som parameter

  4. Migrera från MySQL Enterprise till MariaDB 10.3