PDA

View Full Version : commit(*CS) oder commit(*CHG) verwenden



Rathjen72
30-12-21, 08:20
Hallo,

ich bin neu auf dem Gebiet der Commit-Steuerung und muss sagen, dass das verdammt kompliziert ist.

Wir wollen alle neuen Programme mit Commit-Steuerung laufen lassen und haben schon einige wenige im Einsatz.
Jetzt hat sich herausgestellt, dass bei commit(*CS) Sätze mit einem SQL-Select-Befehl nicht gelesen werden können, wenn eine Altanwendung (ohne Commit-Steuerung) einen Satz sperrt (Ursache vermutlich Lesen einer Update-Datei mit READ ohne folgendes Update).

Deshalb die Frage:
Habe ich das Problem nicht mehr, wenn ich commit(*CHG) nehmen?
Wo genau sind die Unterschiede?

In einigen Vorträgen wurde mit *CS gearbeitet und in einigen mit *CHG.
Somit bin ich nicht sicher, was besser ist.

Habt ihr vielleicht einen Tip/Link, unter dem die Commit-Steuerung User-Freundlich auf Deutsch erklärt wird?

Vielen Dank im Vorraus,
Simone

Fuerchau
30-12-21, 09:07
Leider spart sich die IBM inzwischen die Übersetzungen. Aber man kann sich die Seiten ja auch per Google-Übersetzer ins Deutsche übertragen lassen:
https://www.ibm.com/docs/de/i/7.3?topic=integrity-commitment-control

Außer bei *NONE handelt es sich i.W. um das Sperrverhalten der Daten bereits beim Lesen.
Am einfachsten:
*CHG: es werden nur veränderte und hinzugefügte Daten gesperrt.
*RR: Alle Tabellen der Abfrage werden bis zum Close berreits beim Lesen gegen Veränderungen gesperrt.
*CS: die aktuelle Zeile wird gesperrt bis die nächste Zeile gelesen wird.

*CS stellt daher i.W. sicher, dass keine "Schmutzdaten", also noch nicht committete Daten gelesen werden können, daher die Sperre.
*CHG kann alle Daten lesen, was beim Update in Parallelverarbetung zu unschönen Ergebnissen führen kann.

Zusätzlich gibt es auch noch Sperren bei der Cursordefinition:
Keep Locks: Alle Sperren bis Transaktionsende halten.
For Update: Lese Sperre der gerade gelesenen Zeile um ggf. einen "Update .. where current of .." durchzuführen.

Rathjen72
30-12-21, 11:42
Vielen Dank für die schnelle Antwort.

Auf der IBM-Seite wird zumindest im meinem Browser der Text in Spalte 'Duration of Row Locks' nicht immer neben dem richtigen Text in Spalte 'Commit Paramter' angezeigt (Zeilen sind verrutscht).
Deshalb sah es für mich so aus, dass neben *CHG der Text 'Row locked when read and' steht.
Ich habe mir nun die Doku Database Commitment control 7.2 als PDF herunter geladen.
Da sind die Zeilen nicht verrutscht und *CS und *CHG sind noch genauer erklärt.

BenderD
03-01-22, 12:01
... das kommt auf die Anforderung an:
- mache ich einen select into, brauche ich mindestens *CS, damit ich sicher bin, dass beim darauf folgenden update der Satz nicht durch einen anderen zwischendrin verändert wurde.
- verwende ich einen Cursor und positioned update, ist *CHG ausreichend
- arbeite ich im hohen Transaktionsbereich, kann es sinnvoll sein mit einem dummy update einzusteigen, um sofort eine volle Satzsperre zu bekommen
- will ich primär mehrere updates zu einer Transaktion klammern, geht das mit allem, außer *NONE

Wichtig ist erst einmal zu verstehen, dass es grob fehlerhaft ist, lang andauernde Satzsperren zu setzen => die Altanwendung muss korrigiert werden!!!

D*B

Rathjen72
04-01-22, 08:15
Bisher haben wir commit(*CS) immer mit set option am Anfang des Source angegeben.
Soweit ich weiß gilt das dann immer für das ganze Programm.

Kann man das denn auch im SQL-Befehl direkt angeben?
In der Regel habe ich ja mehrere SQL-Befehle im Programm. Wenn ich das so genau differenzieren möchte, dann müsste ich ggf. unterschiedliche Commit-Level in einem Programm verwenden.

Unsere Altanwendung soll in 1-2 Jahren komplett abgelöst werden. In der neuen Anwendung wird es dann nur noch Datei-Zugriffe mit SQL und Commit-Steuerung geben.
Aus diesem Grund wollen wir die Altanwendung nicht mehr korrigieren.

Fuerchau
04-01-22, 08:54
Schau mal in die Doku, fast alle Befehle haben eine "Isolation Clause":

626

BenderD
04-01-22, 10:48
... set option ist dasselbe, wie die Angabe beim CRTSQLRPGI per Parameter COMMIT und wird eigentlich nur benötigt, wenn irgendwelche Gehörnte den Command default verpfuscht haben.
Wichtig ist hier, dass nicht mit COMMIT(*NONE) gewandelt wird. Innerhalb des Programms kann man dann per SQL Anweisung set transaction isolation switchen (geht allerdings nur an der Transaktionsgrenze). Isolation clause scheint da einfacher, ist allerdings DB2 only und ich empfehle sich da eher an den ANSI Standard zu halten.

Zum Verständnis ist es wichtig die Problme von Multi Benutzer Betrieb von Datenbanken zu verstehen, als Einstieg siehe auch: https://de.wikipedia.org/wiki/Isolation_(Datenbank).

Grundsätzlich gilt ein commit level immer für die gesamte Datenbankverbindung (bei AS/400 ACTGRP des Jobs, es sei denn ein Gehörnter hat das STRCMTL verhunzt). Mit sauberer Modularisierung kann man sich da das Leben vereinfachen, mit Blindflug sogar mehr Durcheinander anrichten als ihr jetzt schon mit den Dauersperren von Sätzen habt.

D*B