update kommt nicht zurück

hmeyer

Benutzer
Beiträge
8
Hallo Leute,
ich würde gerne ein Update-Statement auf einer Oracle-Datenbank ausführen:
Code:
update gb_vw_proc_c_ord_payment set pcme_pay_desc='ORDER' where pcme_ord_id=12348167;
commit;
Das Statement wird ausgeführt, kommt aber mit keiner Meldung zurück, sondern läuft und läuft und läuft. Warum? Auf dem Feld pcme_ord_id ist ein Index.
Normalerweise ist das Statement im Bruchteil einer Sekunde fertig. Wie kann ich die Ursache finden. Ein Select-Statement ist im Bruchteil einer Sekunde durchgelaufen.
Gruß Horst
 
Werbung:
Wahrscheinlich wartet es darauf dass ein Lock auf den Datensatz freigegeben wird.

Vermutlich wurde aus der Anwendung oder von einem anderen SQL Client der gleiche Datensatz geändert, aber kein COMMIT gemacht.
 
Danke für die Rückmeldung. Da es ein Testdatenbank ist, habe ich freie Hand. Wie kann ich denn einen Lock auf den Datensatz manuell setzen?
 
Sorry, aber das funktioniert nicht, der Update-Process bleibt ja schon beim Ausführen von UPDATE hängen, zum commit kommt die Ausführung erst gar nicht...
 
Natürlich kannst Du keinen Lock auf einen Datensatz bekommen, wenn der schon von einer anderen Transaktion gesperrt ist.

Du musst erst die blockierende Transaktion beenden.
 
Wie kann ich denn einen Lock auf den Datensatz manuell setzen?
Code:
select * from gb_vw_proc_c_ord_payment where pcme_ord_id=12348167;
Das würde ein Lock auf den Datensatz (oder mehrere) setzen, wo das Kriterium zutrifft.
Es produziert also eine Sperre auf bestimmten Datensätzen, ohne überhaupt etwas zu ändern. Es macht also diese Sperre, weil der Ausführende explizit "freie Hand" haben möchte, um die Datensätze zu manipulieren und sie vor einer Änderung durch andere zu schützen (bis commit oder rollback)
Der Sperreffekt des Statementes oben ist der gleiche, wie der eines Updates, wie Du es gepostet hast.
Da es ein Testdatenbank ist, habe ich freie Hand
Das impliziert, dass niemand außer Dir Datensätze sperrt und damit die DB bzw. einen der Datensätze in einen Lock bringt.
Es muss also ein Programm laufen oder eine andere Sitzung (Session) von Dir, die zu dem Effekt führt.

Das ist ungewöhnlich und ist Dir ja scheinbar auch noch nie passiert, sonst wüsstest Du, was los ist.

Mögliche Ursachen:
- Ein Programm von Dir läuft parallel und hat das Update (nicht mit Commit) abgeschlossen
- Eine IDE oder ähnliches läuft und hat mit einem solchen Statement zu dem Zustand geführt
- irgendetwas hat dieses (oder mehr ) Statements ausgeführt und ist an ein Limit gelaufen

Limits
Ein mögliches Limit wäre eine größere Transaktion (Volumen bzw. Laufzeit wegen intensiver Berechnung / Mengenfindung), das noch nicht abgeschlossen ist oder durch seine Last ein anderes Limit erreicht hat. Ein konkretes Limit könnte z.B. Festplattenplatz (physikalisch) oder logischer Platz (Tablespace) sein oder Erweiterungsregeln für Tabellenspeicherbereich, die für das Statement nicht ausreichen.

Speichermangel, logisch oder physikalisch, kann gerne auf Testsystemen eintreten (naheliegend), die eben zum Test oder aus Kostengründen (Cloud) (zu) klein ausgelegt sind oder durch einen Programm oder Statementfehler künstlich (fehlerhaft) aufgebläht sind oder deren Platz (Gedächtnis) für die Verarbeitung einer großen Transaktion und das mögliche Rollback nicht groß genug sind.

Ein Zombieprozess hält Sperren und ist nicht ohne gezieltes Suchen erkennbar (GUI Fenster weg, Einzelprozess eines Programm Threads). Zombies entstehen durch Programmierfehler, Schedulefehler bei automatisierten Abläufen per Cron, Scheduled Task oder Oracle eigene Automatisierungsverfahren, die in einen Fehlerzustand laufen, überschneiden usw.

(Auto)Commit Verhalten
Ob Programmcode, IDE oder auch SQLplus (Command Line), alle diese Systeme können im Autocommit laufen. Das wäre nicht ungewöhnlich. Ein beliebiges Update Statement würde also automatisch commited und Dein Problem würde nie auftreten. (Und ein explizites Commit wäre sinnlos/unnötig)

Umgekehrt könntest Du bei einer hinreichend großen DB mit genügend Resourcen (Speicherplatz) und ausgeschaltetem Autocommit und der fortwährenden Nutzung einer einzigen(!), ununterbrochenen Sitzung tagelang Updates, Deletes und Inserts machen, ohne explizites Commit. Das geht vor allem dann, wenn jedes einzelne Statement logisch korrekt ist. Praktisch funktioniert das bspw. wenn Du ein Tutorial an Deinem Laptop durcharbeitest und das Teil abends einfach zu klappst und morgens wieder öffnest.

Erzwungenes Commit
Es wäre möglich, dass Dein System (andere Programmteile oder Scripte) durch irgendetwas explizite oder implizite Commits durchführen, ohne dass sie augenfällig sind. Jedes DDL Statement führt bei Oracle implizit zu einem Commit. Wird soetwas automatisiert durchgeführt, wird also ständig commited (ohne dass der Befehl explizit im Code auftaucht!). Bleibt dies aus, verhält sich das System vermutlich interaktiv anders, als sonst. Programme können explizite Commits enthalten (am schlimmsten in Stored Procs oder Functions). Ein simples Select einer solchen Funktion kann also fortwährend ein Commit verschleiern. Abhängig vom Verlauf einer Session (mit Aufruf einer solchen Funktion oder ohne), ist das Verhalten also vollkommen anders.
Abhängig von der Art bzw. Ursache des Commits geht es bei den aufgeführten Problemen um Effekte, die man interaktiv selbst provoziert hat oder die in einer anderen Sitzung ausgelöst werden.

Möglichkeiten
- Lock finden und löschen, also die Session beenden, die das Lock hält.
- Lock eingrenzen (zum Üben)

Du kannst andere Updates durchführen und ausprobieren, ob sie funktionieren. Lassen sich "Nachbardatensätze" aktualisieren? Damit kannst Du mglw. selbst eine Erklärung finden, was zu dem Lock führt.


Du wirst am ehesten selbst wissen, welches Szenario die Ursache sein könnte. Von hier aus ist es kaum zu erklären.
 
Das würde ein Lock auf den Datensatz (oder mehrere) setzen, wo das Kriterium zutrifft.
Ein SELECT setzt keinen Lock. Du müsstest ein FOR UPDATE hinzufügen, damit der Datensatz gesperrt wird. Das wäre aber letztendlich das Gleiche wie ein UPDATE - wenn der Datensatz bereits gesperrt ist, dann wird gewartet. Um zu prüfen ob der Datensatz gesperrt ist, könnte man for update nowait verwenden. Dann wird sofort ein Fehler geworfen, falls der Datensatz nicht gesperret werden kann.
 
Am besten schauste mal nach, ob denn ein Lock überhaupt drauf ist. Ansonsten kannste natürlich weiter im Nebel stochern.
 
Werbung:
Zurück
Oben