In der Stack Overflow SQL Server 2005-Datenbank werden einige schädliche, aber seltene Deadlock-Bedingungen angezeigt.
Ich habe den Profiler angehängt, mithilfe dieses hervorragenden Artikels zur Fehlerbehebung bei Deadlocks ein Ablaufverfolgungsprofil erstellt und eine Reihe von Beispielen erfasst. Das Seltsame ist, dass das Deadlocking-Schreiben immer dasselbe ist :
UPDATE [dbo].[Posts]
SET [AnswerCount] = @p1, [LastActivityDate] = @p2, [LastActivityUserId] = @p3
WHERE [Id] = @p0
Die andere Deadlocking-Anweisung variiert, aber es ist normalerweise eine Art triviales, einfaches Lesen der Posts-Tabelle. Dieser wird immer in der Sackgasse getötet. Hier ist ein Beispiel
SELECT
[t0].[Id], [t0].[PostTypeId], [t0].[Score], [t0].[Views], [t0].[AnswerCount],
[t0].[AcceptedAnswerId], [t0].[IsLocked], [t0].[IsLockedEdit], [t0].[ParentId],
[t0].[CurrentRevisionId], [t0].[FirstRevisionId], [t0].[LockedReason],
[t0].[LastActivityDate], [t0].[LastActivityUserId]
FROM [dbo].[Posts] AS [t0]
WHERE [t0].[ParentId] = @p0
Um ganz klar zu sein, sehen wir keine Deadlocks beim Schreiben / Schreiben, sondern beim Lesen / Schreiben.
Wir haben momentan eine Mischung aus LINQ- und parametrisierten SQL-Abfragen. Wir haben with (nolock)
alle SQL-Abfragen hinzugefügt . Dies mag einigen geholfen haben. Wir hatten auch eine einzige (sehr) schlecht geschriebene Abzeichenabfrage, die ich gestern behoben habe. Die Ausführung dauerte jedes Mal mehr als 20 Sekunden und lief jede Minute darüber hinaus. Ich hatte gehofft, dass dies die Ursache für einige der Schließprobleme war!
Leider habe ich vor ca. 2 Stunden einen weiteren Deadlock-Fehler erhalten. Gleiche exakte Symptome, gleiche exakte Schuldige schreiben.
Das wirklich Seltsame ist, dass die oben gezeigte SQL-Anweisung zum Sperren von Schreibvorgängen Teil eines sehr spezifischen Codepfads ist. Es wird nur ausgeführt, wenn einer Frage eine neue Antwort hinzugefügt wird. Die übergeordnete Frage wird mit der neuen Antwortanzahl und dem letzten Datum / Benutzer aktualisiert. Dies ist offensichtlich nicht so häufig im Vergleich zu der enormen Anzahl von Lesevorgängen, die wir durchführen! Soweit ich das beurteilen kann, schreiben wir nirgendwo in der App eine große Anzahl von Schreibvorgängen.
Mir ist klar, dass NOLOCK eine Art Riesenhammer ist, aber die meisten Abfragen, die wir hier ausführen, müssen nicht so genau sein. Interessiert es Sie, wenn Ihr Benutzerprofil einige Sekunden veraltet ist?
Die Verwendung von NOLOCK mit Linq ist etwas schwieriger, wie Scott Hanselman hier erläutert .
Wir flirten mit der Idee zu verwenden
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
im Basisdatenbankkontext, sodass alle unsere LINQ-Abfragen diesen Satz haben. Ohne das müssten wir jeden LINQ-Aufruf, den wir tätigen (also die einfach lesenden, die die überwiegende Mehrheit von ihnen sind), in einen hässlichen Transaktionscodeblock mit 3-4 Zeilen packen, was hässlich ist.
Ich glaube, ich bin ein wenig frustriert darüber, dass triviale Lesevorgänge in SQL 2005 beim Schreiben zum Stillstand kommen können. Ich konnte sehen, dass Deadlocks beim Schreiben / Schreiben ein großes Problem sind, aber liest? Wir betreiben hier keine Bank-Site, wir brauchen nicht jedes Mal perfekte Genauigkeit.
Ideen? Gedanken?
Instanziieren Sie für jede Operation ein neues LINQ to SQL DataContext-Objekt oder teilen Sie möglicherweise für alle Ihre Aufrufe denselben statischen Kontext?
Jeremy, wir teilen größtenteils einen statischen Datenkontext im Basis-Controller:
private DBContext _db;
/// <summary>
/// Gets the DataContext to be used by a Request's controllers.
/// </summary>
public DBContext DB
{
get
{
if (_db == null)
{
_db = new DBContext() { SessionName = GetType().Name };
//_db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}
return _db;
}
}
Empfehlen Sie, dass wir für jeden Controller oder pro Seite oder öfter einen neuen Kontext erstellen?