Ungefähr einmal pro Woche muss ich eine Blockierungskette in einer SQL Server 2005-Datenbank auflösen, die durch eine langlebige Lesesperre von einem Access 2003-Frontend verursacht wird. Die Sperre wird aufgehoben, wenn ein Benutzer ein bestimmtes Formular öffnet, und wird freigegeben, sobald der Benutzer das Bildlauf durch das Formular abgeschlossen oder es geschlossen hat. Da viele unserer Benutzer dieses Formular als Referenz öffnen, bleiben diese Sperren eine Weile bestehen. Jede Aktualisierung der Tabelle führt zur Blockierung, und plötzlich kann niemand mehr aus dieser Tabelle auswählen, da alle auf die erste Sperre warten. Dies ist für uns ein ziemliches Problem, da viele Apps auf diesen Daten basieren. Ich verstehe, dass dieses Sperrverhalten Teil der Funktionsweise von Access mit verknüpften Tabellen ist.
Ich habe das Problem mit Activity Monitor gelöst, indem ich den SELECT-Prozess, der der Head Blocker ist, beendet habe, wenn ich davon erfahre. Dies ist nicht nur deshalb ein Problem, weil ich Zeit brauche, um es manuell zu machen, sondern auch, weil es reaktiv ist. Als ich davon höre, war es für viele Menschen bereits ein Problem.
Ich würde gerne wissen, ob es eine automatische Möglichkeit gibt, nach diesen langlebigen Blockierungsketten zu suchen und entweder per E-Mail benachrichtigt zu werden oder das Problem automatisch zu lösen. Die Logik scheint recht einfach zu sein ("Wenn ein Prozess, der mit dieser SELECT-Abfrage übereinstimmt, länger als eine Minute blockiert wurde, benachrichtigen Sie mich / beenden Sie ihn"), aber ich weiß nicht, wie ich dies mit SQL Server implementieren soll.
Ich denke, die richtige Lösung besteht darin, die App zu reparieren oder neu zu schreiben. Aufgrund der Abteilungspolitik ist dies jedoch für die nächsten Monate keine Option, daher suche ich nach einer Notlösung.
quelle
Antworten:
Haben Sie überlegt, die Snapshot-Isolation zu verwenden ? Durch Aktivieren von read_committed_snapshot in der Datenbank werden alle Lesevorgänge (Auswahlen) gesperrt:
Keine Anwendungsänderungen. Einige Semantiken ändern sich unter Snapshot und Ihre Anwendung reagiert möglicherweise komisch, aber das ist die Ausnahme, nicht die Norm. Die überwiegende Mehrheit der Anwendungen bemerkt keinen Unterschied, sie erhalten lediglich eine kostenlose Leistungssteigerung.
Wie auch immer, ich möchte auch die ursprüngliche Frage beantworten: Wie man eine lange laufende Abfrage erkennt (und möglicherweise tötet). Eigentlich macht der Motor das schon für Sie. Beim Überschreiten eines Schwellenwerts wird ein Ereignis ausgelöst : Ereignisklasse "Blockierter Prozessbericht" . Der Schwellenwert wird über die Option Blockierter Prozessschwellenwert konfiguriert . Jedes Ablaufverfolgungsereignis kann in eine Ereignisbenachrichtigung umgewandelt werden, und Ereignisbenachrichtigungen können Prozeduren aktivieren . Verbinden Sie die Punkte, und Sie haben bei Bedarf aktivierten Code, der ausgeführt wird, wenn die Engine eine Abfrage erkennt, die einen Ausführungszeitschwellenwert überschritten hat. Keine Abfrage, keine Überwachung. Beachten Sie jedoch, dass die Benachrichtigung asynchron istZum Zeitpunkt der Verarbeitung ist die Abfrage möglicherweise abgeschlossen, sodass dies berücksichtigt werden muss.
Hier ist ein Beispiel:
Richten Sie nun in einer neuen Abfrage eine
WAITFOR
erwartete Benachrichtigung ein:Und mach weiter und verursache eine Blockade. Ich habe einen Prozess verwendet, der eine Tabelle erstellt und nicht festgeschrieben hat, und in einem anderen Abfragefenster habe ich versucht, aus der Tabelle auszuwählen. In 20 Sekunden (mein konfigurierter Schwellenwert oben) erhielt ich den Sperrbericht:
Ich überlasse es dem Leser, dies als Übung in einen automatisierten Prozess zu packen. Und ja, die Warteschlange / der Dienst / die aktivierte Prozedur muss sich in befinden
[msdb]
.quelle
Sie können entweder Ihr eigenes Überwachungstool erstellen oder nach einer Lösung eines Drittanbieters suchen, die eine für Sie bereitstellt. Wenn Sie daran interessiert sind, Ihre eigene Version zu erstellen, hängt dies davon ab, mit welcher Version von SQL Server Sie arbeiten. Wenn es 2005 ist, können Sie das Trace-Ereignis Blocked Process Report verwenden . Wenn Sie 2008 oder höher ausführen, würde ich empfehlen, das entsprechende erweiterte Ereignis blocked_process_report zu verwenden. Jonathan Kehayias hat eine gute Beschreibung, wie man es benutzt.
Wenn Sie sich Produkte von Drittanbietern ansehen, hat der SQL Monitor der Red Gate-Software Prozess- und lang laufende Prozesswarnungen integriert.
quelle
Obwohl hier nicht beschrieben wird, wie Sie über das Problem informiert werden, zeigt Ihnen dieses Verfahren, wie Sie abfragen, ob eine Blockierung vorliegt. Es werden auch Kill-Befehle für Sie generiert, wenn Sie den richtigen Parameter übergeben.
Hoffe das gibt dir ein paar Ideen.
quelle
Ich würde vorschlagen, das folgende Thema des MSDN- Forums zu lesen . Es geht um das Sperren durch den Zugriff auf eine SQL Server-Datenbank. Der Vorschlag besteht hauptsächlich darin, über Abfragen mit dem NOLOCK-Hinweis auf die Tabellen zuzugreifen, damit keine Sperrprobleme auftreten. NOLOCK ist nicht die beste Lösung, da es andere Probleme verursachen kann, aber die meisten Ihrer Sperrprobleme reduziert.
Die bessere Lösung wäre, Remus 'Idee zu implementieren, die Snapshot-Isolation in Ihrer Datenbank einzurichten. Oder implementieren Sie die Snapshot-Isolationsstufe nur für bestimmte Verbindungen, die Blockierungen verursachen.
Um Ihren Server ordnungsgemäß auf Blockierungsprobleme zu überwachen, würde ich Folgendes vorschlagen:
Wenn Sie eine proaktive Antwort auf dieses Problem wünschen, anstatt jede Stunde einen Job zum Überwachen der Traces zu haben, lassen Sie ihn jede Minute laufen und beenden Sie alle führenden blockierenden Access-Sitzungen.
quelle
Nach der hervorragenden Antwort von @Remus Rusanu habe ich die Aufgabe des Lesers übernommen, das Ereignis mit einer gespeicherten Prozedur zu verbinden.
In meinem Fall schreibt der sp die XML des blockierenden Ereignisses in eine Tabelle, aber Sie können an dieser Position tun, was Sie wollen.
Folgen Sie also Remus 'Code und erstellen Sie das
queue
, dasservice
und dasnotification
mit einem einfachen Kopieren / Einfügen von oben. Fügen Sie diesp_configure
Optionen hinzu und Sie sind im Grunde genommen eingestellt.Das einzige was noch zu tun ist ist
queue
Sobald Sie den SP aktiviert haben, fließen die Ereignisse in Ihre Tabelle.
Ich fand heraus, dass sich die Warteschlange sofort selbst deaktiviert, wenn der SP einen Fehler aufweist. In diesem Fall müssen Sie zu Server Studio gehen und es im Kontextmenü des Warteschlangeneintrags erneut aktivieren
[msdb]->Service Broker->Warteschlangen
.Ich habe einige Zeit gebraucht, um dies zum Laufen zu bringen und die richtigen Stellen in der Dokumentation zu finden. Ich nehme an, dass dies auch für andere hilfreich ist. Ich verwende SQLServer 2005.
Erstellen Sie den SP ohne Argumente
Erstellen Sie die
pdix_lock_events
TabelleAktivieren Sie den SP auf dem
queue
quelle