{"id":3225,"date":"2009-07-21T21:17:03","date_gmt":"2009-07-21T19:17:03","guid":{"rendered":"http:\/\/www.glorf.it\/blog\/?p=3225"},"modified":"2009-07-21T21:17:03","modified_gmt":"2009-07-21T19:17:03","slug":"command-timeout-hinterlaesst-offene-transaktionen","status":"publish","type":"post","link":"http:\/\/www.glorf.it\/blog\/2009\/07\/21\/sql-talk\/command-timeout-hinterlaesst-offene-transaktionen","title":{"rendered":"Command-Timeout hinterl&#228;sst offene Transaktionen"},"content":{"rendered":"<p>In der <a href=\"http:\/\/www.glorf.it\/blog\/2009\/07\/20\/sql-server\/verschiedene-timeouts-bei-der-abfrageausfuehrung\">gestrigen Liste kommen jede Menge Timeouts<\/a> vor, die zu einer Fehlermeldung bei der Bearbeitung von SQL-Befehlen f&#252;hren k&#246;nnen. Heute stellten wir fest, dass ein &quot;Command Timeout&quot; in der Anwendung (also am Client) am SQL-Server zu offenen Transaktionen f&#252;hren k&#246;nnen.<\/p>\n<p>Beispiel: Die Anwendung schickt einen SQL-Batch an den SQL-Server der am St&#252;ck ausgef&#252;hrt werden soll:<\/p>\n<p><code lang=\"sql\">BEGIN TRANSACTION;<br \/>\nINSERT &#8230;. SELECT &#8230;.; &#8211; irgendetwas schrecklich Langes<br \/>\nCOMMIT;<\/code><\/p>\n<p>Wenn das zu lange dauert und das Client-API daher einen Command-Timeout wirft, dann schickt der Client per TDS einen &quot;Cancel&quot; zum Server. Das sah ich leider nur mit dem NetMon, nicht via Profiler. Der SQL-Server unterbricht dann sofort die Ausf&#252;hrung des aktuellen Batches. Aus dem Batch wird kein weiterer Befehl ausgef&#252;hrt. Auch kein ROLLBACK, dass in einem CATCH-Block im SQL-Batch enthalten ist. Die Transaktion bleibt einfach offen. Damit hatte ich nicht gerechnet.<\/p>\n<p>Daher muss man in der Fehlerbehandlung der Anwendung immer mal noch einen SQL-Befehl &#252;ber die Connection schicken, selbst wenn die Transaktion komplett als Batch an den SQL-Server geschickt wurde. Das geht beispielsweise mit einem bedingten ROLLBACK:<\/p>\n<p><code lang=\"sql\">IF @@TRANCOUNT > 0 ROLLBACK;<\/code><\/p>\n<p>Ausprobiert haben wir ODBC und ADO.net. Bei beiden war es so. Bei ODBC mag es ja meistens noch gereicht haben die Connection einfach zu beenden, was zu einem Rollback f&#252;hrt. Bei ADO.net reicht das normalerweise nicht. Hier ist der bedingte ROLLBACK-Befehl fast immer n&#246;tig, weil bei ADO.net in der Regel Connection-Pooling verwendet wird: eine geschlossene Verbindung wandert zur&#252;ck in den Pool, sie wird nicht wirklich geschlossen. Erst beim Rausholen aus dem Pool wird zum Zweck des Recycling ein &quot;Reset&quot; auf der Connection abgesetzt, dass alle Optionen zur&#252;cksetzt, Transaktionen schlie&#223;t und Sperren freigibt. Diese Kombination kann dazu f&#252;hren, dass Zombi-Sperren sehr lange gehalten werden und zu einem h&#252;bschen Blockierungsproblem f&#252;hren&#8230; \ud83d\ude09<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In der gestrigen Liste kommen jede Menge Timeouts vor, die zu einer Fehlermeldung bei der Bearbeitung von SQL-Befehlen f&#252;hren k&#246;nnen. Heute stellten wir fest, dass ein &quot;Command Timeout&quot; in der Anwendung (also am Client) am SQL-Server zu offenen Transaktionen f&#252;hren k&#246;nnen. Beispiel: Die Anwendung schickt einen SQL-Batch an den SQL-Server der am St&#252;ck ausgef&#252;hrt werden [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3],"tags":[537,929],"_links":{"self":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/3225"}],"collection":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/comments?post=3225"}],"version-history":[{"count":5,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/3225\/revisions"}],"predecessor-version":[{"id":3231,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/posts\/3225\/revisions\/3231"}],"wp:attachment":[{"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/media?parent=3225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/categories?post=3225"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.glorf.it\/blog\/wp-json\/wp\/v2\/tags?post=3225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}