wake-up-neo.com

Wie kann man verhindern, dass das Zeitlimit für Abfragen abgelaufen ist? (SQLNCLI11-Fehler '80040e31')

Ich habe eine Verbindung zu einer MS SQL Server 2012-Datenbank in klassischem ASP (VBScript). Dies ist meine Verbindungszeichenfolge:

Provider=SQL Server Native Client 11.0;Server=localhost;
Database=databank;Uid=myuser;Pwd=mypassword;

Wenn ich diesen SQL-Befehl ausführe:

UPDATE [info] SET [stamp]='2014-03-18 01:00:02',
[data]='12533 characters goes here',
[saved]='2014-03-18 01:00:00',
[confirmed]=0,[ip]=0,[mode]=3,[rebuild]=0,
[updated]=1,[findable]=0 
WHERE [ID]=193246;

Ich erhalte folgenden Fehler:

Microsoft SQL Server Native Client 11.0 
error '80040e31'
Query timeout expired   
/functions.asp, line 476

Die SQL-Abfrage ist ziemlich lang, das Datenfeld wird mit 12533 ​​Zeichen aktualisiert. Die ID-Spalte ist indiziert, daher sollte es schnell gehen, den Beitrag mit der ID 193246 zu finden.

Wenn ich den exakt gleichen SQL-Ausdruck (kopiert und eingefügt) in SQL Server Management Studio ausführe, wird dieser in kürzester Zeit erfolgreich ausgeführt. Kein Problem. Es gibt also kein Problem mit SQL selbst. Ich habe sogar versucht, ein ADODB.Recordset-Objekt zu verwenden und über dieses zu aktualisieren (kein selbst geschriebenes SQL), aber ich erhalte immer noch den gleichen Timeout-Fehler.

Wenn ich im Management Studio zu Extras> Optionen> Abfrageausführung gehe, wird das Ausführungszeitlimit auf 0 (unendlich) festgelegt. Unter Extras> Optionen> Designer wird das Transaktionszeitlimit auf 30 Sekunden festgelegt. Dies sollte ausreichen, da sich das Skript und die Datenbank auf demselben Computer befinden ("localhost" befindet sich in der Verbindungszeichenfolge).

Was geht hier vor sich? Warum kann ich SQL im Management Studio ausführen, aber nicht in meinem ASP Code?


Bearbeiten: Es wurde versucht, das 30-Sekunden-Zeitlimit auf der Registerkarte Designer auf 600 Sekunden einzustellen, um sicherzustellen, dass der Fehler weiterhin auftritt (tritt übrigens nach 30 Sekunden Laden der Seite auf).

Hier ist der Code, den ich verwende, um SQL auf der Seite ASP auszuführen:

Set Conn = Server.CreateObject("ADODB.Connection")
Conn.Open "Provider=SQL Server Native Client 11.0;
Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;"
Conn.Execute "UPDATE [info] SET [stamp]='2014-03-18 01:00:02',
[data]='12533 characters goes here',[saved]='2014-03-18 01:00:00',
[confirmed]=0,[ip]=0,[mode]=3,[rebuild]=0,[updated]=1,[findable]=0 
WHERE [ID]=193246;"

Edit 2: Mit Conn.CommandTimeout = 0, um eine unendliche Ausführungszeit für die Abfrage anzugeben, bewirkt nichts, dass die Abfrage nur für immer ausgeführt wird. 25 Minuten gewartet und es wurde noch ausgeführt.

Ich habe dann versucht, die SQL in zwei SQL-Anweisungen zu unterteilen, die lange Datenaktualisierung in der einen und die andere Aktualisierung in der anderen. Das lange Datenfeld wurde immer noch nicht aktualisiert, es ist nur eine Zeitüberschreitung aufgetreten.

Ich habe dies mit zwei zusätzlichen Verbindungszeichenfolgen versucht:

Driver={SQL Server};Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;
Driver={SQL Server Native Client 11.0};Server=localhost;Database=databank;Uid=myuser;Pwd=mypassword;

Hat nicht funktioniert Ich habe sogar versucht, die Daten auf 12533 ​​A zu ändern, um festzustellen, ob die tatsächlichen Daten das Problem verursachen. Nein, das gleiche Problem.

Dann habe ich etwas Interessantes herausgefunden: Ich habe versucht, zuerst das kurze SQL auszuführen, bevor das Datenfeld lange aktualisiert wurde. Es hat auch eine Ausnahme für das Zeitlimit für Abfragen ...

Aber wieso? Es muss so wenig aktualisiert werden (die gesamte SQL-Anweisung enthält weniger als 200 Zeichen). Wird weiter untersuchen.


Edit 3: Ich dachte, es könnte etwas mit dem Login zu tun haben, aber ich habe nichts gefunden, was falsch aussah. Ich habe sogar versucht, die Verbindungszeichenfolge zu ändern, um das sa-Konto zu verwenden, aber selbst das hat nicht funktioniert, und es wurde immer noch "Abfrage-Timeout abgelaufen" angezeigt.

Das macht mich verrückt. Es gibt keine Lösung, keine Umgehung und am schlimmsten keine Ideen!


Edit 4: Ging im Management Studio zu Extras> Optionen> Designer und aktivierte das Kontrollkästchen "Speichern von Änderungen verhindern, die eine Neuerstellung der Tabelle erfordern". Es hat nichts getan.

Es wurde versucht, den Spaltendatentyp "data" von "nvarchar (MAX)" in den minderwertigen Typ "ntext" zu ändern (ich werde verzweifelt). Es hat nicht funktioniert.

Versucht, die kleinste Änderung an der Stelle auszuführen, die mir einfällt:

UPDATE [info] SET [confirmed]=0 WHERE [ID]=193246;

Das würde eine Bitspalte auf falsch setzen. Hat nicht funktioniert Ich habe versucht, genau dieselbe Abfrage im Management Studio auszuführen, und sie hat einwandfrei funktioniert.

Wirf mir ein paar Ideen zu, wenn du sie hast, weil mir jetzt wirklich die Puste ausgeht.


Edit 5: Habe jetzt auch folgenden Verbindungsstring ausprobiert:

Provider=SQLOLEDB.1;Password=mypassword;Persist Security Info=True;User ID=myuser;Initial Catalog=databank;Data Source=localhost

Hat nicht funktioniert Versuchte nur, bestätigte auf falsch zu setzen, bekam aber trotzdem eine Auszeit.


Edit 6: Habe jetzt versucht, einen anderen Beitrag in der gleichen Tabelle zu aktualisieren:

UPDATE [info] SET [confirmed]=0 WHERE [ID]=1;

Es gab auch den Timeout-Fehler. Jetzt wissen wir also, dass es nicht postspezifisch ist.

Ich kann Posts in anderen Tabellen in derselben Datenbank über ASP aktualisieren. Ich kann auch Tabellen in anderen Datenbanken auf localhost aktualisieren.

Könnte etwas mit der [info] -Tabelle kaputt sein? Ich habe den MS Access-Assistenten zum automatischen Verschieben von Daten von Access zu MS SQL Server 2012 verwendet, Spalten des Datentyps "ntext" erstellt und diesen manuell in "nvarchar (MAX)" geändert, da ntext veraltet ist. Könnte etwas kaputt gegangen sein? Ich musste die Tabelle neu erstellen, als ich den Datentyp änderte.

Ich muss etwas schlafen, aber ich werde sicher morgen nachsehen, ob jemand auf mich geantwortet hat. Bitte tun Sie dies, auch wenn Sie nur etwas Ermutigendes zu sagen haben.


Edit 7: Schnelle Bearbeitung vor dem Schlafengehen. Versucht, den Provider auch in der Verbindungszeichenfolge als "SQLNCLI11" zu definieren (unter Verwendung des Namens DLL anstelle des tatsächlichen Providernamens). Es macht keinen Unterschied. Die Verbindung wird genauso gut erstellt wie die Timeout passiert immer noch.

Außerdem verwende ich MS SQL Server 2012 Express nicht (soweit ich weiß, wurde "Express" während der Installation nirgendwo erwähnt). Es ist die ganze Sache.

Wenn es hilft, finden Sie hier die Informationen "Hilfe"> "Über ...", die vom Management Studio bereitgestellt werden:

Microsoft SQL Server Management Studio: 11.0.2100.60  
Microsoft Analysis Services Client Tools: 11.0.2100.60  
Microsoft Data Access Components (MDAC): 6.3.9600.16384  
Microsoft MSXML: 3.0 5.0 6.0   
Microsoft Internet Explorer: 9.11.9600.16521  
Microsoft .NET Framework: 4.0.30319.34011  
Operating System: 6.3.9600

Edit 8 (auch als "Programmierer schlafen nie" bezeichnet):

Nachdem ich einige Dinge ausprobiert hatte, versuchte ich schließlich, die Datenbankverbindung zu schließen und wieder zu öffnen, bevor ich die SQL-Anweisungen ausführte. Es hat plötzlich funktioniert. Was zum...?

Ich hatte meinen Code in einer Subroutine und es stellte sich heraus, dass der Beitrag, den ich zu aktualisieren versuchte, bereits geöffnet war! Der Grund für das Timeout war also, dass der Beitrag oder die gesamte Tabelle wurde durch genau dieselbe Verbindung gesperrt, die versucht hat, ihn zu aktualisieren. Die Verbindung (oder der CPU-Thread) wartete also auf eine Sperre, die niemals aufgehoben werden würde.

Hassen Sie es, wenn es sich herausstellt, dass es so einfach ist, nachdem Sie es so hart versucht haben.

Der Beitrag wurde außerhalb des Unterprogramms mit diesem einfachen Code geöffnet:

Set RecSet = Conn.Execute("SELECT etc")

Ich habe gerade das Folgende hinzugefügt, bevor ich das Unterprogramm aufrufe.

RecSet.Close
Set RecSet = Nothing

Der Grund, warum mir das nie in den Sinn gekommen ist, ist einfach, dass dies in MS Access erlaubt war, aber jetzt habe ich zu MS SQL Server gewechselt und es war nicht so nett (oder eher schlampig). Das von Conn.Execute () erstellte RecSet hatte zuvor noch nie einen gesperrten Eintrag in der Datenbank erstellt, tat dies jedoch plötzlich. Nicht allzu seltsam, da sich die Verbindungszeichenfolge und die tatsächliche Datenbank geändert hatten.

Ich hoffe, dass dieser Beitrag jemand anderem Kopfschmerzen erspart, wenn Sie von MS Access auf MS SQL Server migrieren. Obwohl ich mir nicht vorstellen kann, dass es heutzutage noch so viele Access-Benutzer auf der Welt gibt.

13
user3435078

Es stellt sich heraus, dass der Post (oder besser gesagt die ganze Tabelle) durch dieselbe Verbindung gesperrt wurde, mit der ich versucht habe, den Post zu aktualisieren.

Ich hatte einen geöffneten Datensatz des Posts, der erstellt wurde von:

Set RecSet = Conn.Execute()

Diese Art von Recordset sollte schreibgeschützt sein und als ich MS Access als Datenbank verwendete, hat es nichts gesperrt. Aber anscheinend hat diese Art von Datensatz auf MS SQL Server 2012 etwas gesperrt, weil ich diese Codezeilen hinzugefügt habe, bevor ich die UPDATE SQL-Anweisung ausgeführt habe ...

RecSet.Close
Set RecSet = Nothing

... alles hat gut funktioniert.

Unterm Strich sollten Sie also mit geöffneten Datensatzgruppen vorsichtig sein - auch wenn diese schreibgeschützt sind, können sie Ihre Tabelle vor Aktualisierungen schützen.

12
user3435078