none
Wird Stored Procedure bei Timeout komplett zurückgerollt? RRS feed

  • Frage

  • Ich habe eine Stored Procedure, die wie folgt aussieht:

    CREATE PROCEDURE dbo.ProzedurINSERT
    AS
    BEGIN
      INSERT INTO dbo.Tabelle1 (
      ...
      Felder
      ...)
      VALUES (
      ...
      Werte
      ...)
      INSERT INTO dbo.Tabelle2 (
      ...
      Felder
      ...)
      VALUES (
      ...
      Werte
      ...)
      INSERT INTO dbo.Tabelle3 (
      ...
      Felder
      ...)
      VALUES (
      ...
      Werte
      ...)
    END

      Wenn ein Client diese Prozedur aufruft, kommt es gelegentlich vor, dass der Aufruf nicht abgeschlossen werden kann, ins Timeout läuft. Das liegt dann aller Wahrscheinlich keit nach an Tabelle3.

      Frage: Wenn der Prozedur-Ablauf beim INSERT in Tabelle3 hängen bleibt und per Timeout beendet wird, findet dann ein Rollback für den gesamten Prozedur-Ablauf statt, also auch für die INSERTs in Tabelle1 und Tabelle2? Wenn ja, wie kann ich das verhindern? Wenn das INSERT in Tabelle3 fehlschlägt sollen auf jeden Fall die INSERTs in Tabelle1 und Tabelle2 erhalten bleiben.

    Gruß,

    Matthias

    Donnerstag, 10. Juni 2010 11:42

Antworten

  • Hallo Matthias,

    Prozedur hin oder her:
    Solange Du keine Vorkehrungen triffst, wird kein Rollback vorgenommen.

    In der Voreinstellung befindet sich der SQL Server im AutoCommit Modus
    und so würde jede Anweisung für sich behandelt werden.

    Du muß schon explizit eine Transaktion erstellen und entweder einen TRY CATCH Block
    oder aber jede Anweisung auf einen Fehler (@@ERROR) überprüfen.
    Mehr siehe http://www.sommarskog.se/error_handling_2005.html
    (und Link dort für ältere Versionen, Hintergrund)

    Wenn Du jede Anweisung (auch 1 + 2) für sich behandeln willst,
    würde es bei Dir ausnahmsweise ohne gehen.

    Gruß Elmar

    Donnerstag, 10. Juni 2010 12:11
    Beantworter
  • Hallo Matthias
     
    Die einfachste Methode ist, Transaktionen zu verwenden. Wenn Du willst, dass
    die Tabellen 1 und 2 befüllt bleiben, aber Tabelle 1 zurückgerollt wird,
    wenn es zu einem Fehler in Tabelle 2 kommt, dann kapsle die ersten beiden
    Inserts in eine Transaktion. Etwa so:
     
    Matthias Schuppe wrote:
    > CREATE PROCEDURE dbo.ProzedurINSERT
    > AS
    > BEGIN
     
    BEGIN TRANSACTION
     
    > INSERT INTO dbo.Tabelle1 (
    > ...
    > Felder
    > ...)
    > VALUES (
    > ...
    > Werte
    > ...)
    > INSERT INTO dbo.Tabelle2 (
    > ...
    > Felder
    > ...)
    > VALUES (
    > ...
    > Werte
    > ...)
     
    COMMIT TRANSAKTION
     
    > INSERT INTO dbo.Tabelle3 (
    > ...
    > Felder
    > ...)
    > VALUES (
    > ...
    > Werte
    > ...)
    > END
     
    Nun sollte, wenn es in Tabelle 3 zu einem Fehler kommt, der Inhalt von
    Tabelle 1 und 2 erhalten bleiben. Falls allerdings ein Fehler bei Tabelle 2
    auftritt, wird auch der Inhalt der Tabelle 1 zurückgesetzt.
     
    Gruss
    Henry
     
     

    [MVP Office Access]
    Mittwoch, 16. Juni 2010 03:19

Alle Antworten

  • Hallo Matthias,

    Prozedur hin oder her:
    Solange Du keine Vorkehrungen triffst, wird kein Rollback vorgenommen.

    In der Voreinstellung befindet sich der SQL Server im AutoCommit Modus
    und so würde jede Anweisung für sich behandelt werden.

    Du muß schon explizit eine Transaktion erstellen und entweder einen TRY CATCH Block
    oder aber jede Anweisung auf einen Fehler (@@ERROR) überprüfen.
    Mehr siehe http://www.sommarskog.se/error_handling_2005.html
    (und Link dort für ältere Versionen, Hintergrund)

    Wenn Du jede Anweisung (auch 1 + 2) für sich behandeln willst,
    würde es bei Dir ausnahmsweise ohne gehen.

    Gruß Elmar

    Donnerstag, 10. Juni 2010 12:11
    Beantworter
  • Hallo Matthias
     
    Die einfachste Methode ist, Transaktionen zu verwenden. Wenn Du willst, dass
    die Tabellen 1 und 2 befüllt bleiben, aber Tabelle 1 zurückgerollt wird,
    wenn es zu einem Fehler in Tabelle 2 kommt, dann kapsle die ersten beiden
    Inserts in eine Transaktion. Etwa so:
     
    Matthias Schuppe wrote:
    > CREATE PROCEDURE dbo.ProzedurINSERT
    > AS
    > BEGIN
     
    BEGIN TRANSACTION
     
    > INSERT INTO dbo.Tabelle1 (
    > ...
    > Felder
    > ...)
    > VALUES (
    > ...
    > Werte
    > ...)
    > INSERT INTO dbo.Tabelle2 (
    > ...
    > Felder
    > ...)
    > VALUES (
    > ...
    > Werte
    > ...)
     
    COMMIT TRANSAKTION
     
    > INSERT INTO dbo.Tabelle3 (
    > ...
    > Felder
    > ...)
    > VALUES (
    > ...
    > Werte
    > ...)
    > END
     
    Nun sollte, wenn es in Tabelle 3 zu einem Fehler kommt, der Inhalt von
    Tabelle 1 und 2 erhalten bleiben. Falls allerdings ein Fehler bei Tabelle 2
    auftritt, wird auch der Inhalt der Tabelle 1 zurückgesetzt.
     
    Gruss
    Henry
     
     

    [MVP Office Access]
    Mittwoch, 16. Juni 2010 03:19