Transactions für StoredProcedures

Forum zu diversen Themen rund um die Firebird-Programmierung

Moderator: martin.koeditz

Antworten
zappa2
Beiträge: 3
Registriert: Fr 5. Okt 2018, 10:59

Do 16. Mai 2019, 07:50

Ist es korrekt, bei StoredProcedures, in denen ausschließlich etwas gelesen wird, die zugeordnete Transaction mit einem Rollback zu beenden oder ist immer ein Commit vorzuziehen?

Ich bin bisher immer davon ausgegangen, dass ich nur dann ein Commit benötige, wenn Daten irgendwie verändert wurden.

Und bei StoredProcedures, die -ohne visuelle Komponenten- nur bspw. einen Wert lesen, benutze ich kein Retaining, gleich ob Rollback oder Commit.
bfuerchau
Beiträge: 65
Registriert: Mo 7. Mai 2018, 18:09

Fr 17. Mai 2019, 11:02

Innerhalb von Function/Proceduren ist Commit/Rollback verboten.
Soviel erst mal dazu.
Vom Client aus muss man tatsächlich immer eine neue Transaktion starten, dann Daten lesen und anschließend committen.
Dies liegt an der grundsätzlichen Versionierung von Daten in der Firebird.

Wenn Daten verändert werden (Update/Delete/Insert), wird eine neue Satzversion mit der aktuellen Transaktionsid angelegt.
Die vorherigen Daten werden nur als ungültig markiert, zumal ggf. noch ein Rollback möglich ist.

Sollte dein Clientprozess eine offene Verbindung mit einer offenen Transaktion haben, erhält nun dieser noch immer die alten Daten, da deine Transaktionsid älter ist, als die der neu veränderten Daten.

Mit jedem Start einer neuen Transaktion, können die alten Daten dann automatisch entfernt werden.
Hat nur ein Prozess eine Transaktion ewig lange offen, führt dies ebenso zu einem starken Anwachsen der Datenbank sowie zu z.T. massiven Performanceeinbrüchen, da die vorherigen Satzversionen einer Tabelle immer überlesen werden müssen. Firebird führt da keinen Index um die Daten schneller zu finden.
Beim Überlesen wird geprüft, ob die Transaktionsid der markierten Daten älter ist, als die älteste offene Transaktion, und gibt diese Datenblöcke dann auch tatsächlich für die Wiederverwendung frei.
Parallel dazu wird auch ab und an ein Sweeper-Prozess gestartet, der alle alten Daten sucht um an Hand der ältesten Transationsid diese dann aufzuräumen, was allerdings auch nicht immer klappt.

Dazu sollte man sich regelmäßig die MON$DATABASE ansehen. Wenn die Differenz der ältesten und nächsten Transaktionsid dei 100.000 übersteigt, ist ein Backup/Restore erforderlich um die Datenbank mal wieder gründlich aufzuräumen.
jhoehne
Beiträge: 10
Registriert: Di 11. Dez 2018, 09:19

Mo 20. Mai 2019, 18:07

Seit ich im Firebird-Buch folgendes gelesen habe:
"Transactions in the rolled-back state are not garbage-collected. They remain interesting until a database sweep tags them as “committed” and releases them for garbage collection. In systems with low contention, a periodic manual sweep may be all that’s needed to deal with them."
commite ich auch alle Transaktionen, die nur lesen (und setze bei denen explizit das "read only" Flag).
--
Joachim
bfuerchau
Beiträge: 65
Registriert: Mo 7. Mai 2018, 18:09

Di 21. Mai 2019, 09:24

Wobei das Buch wohl noch nicht aktualisiert wurde.
https://firebirdsql.org/manual/gfix-housekeeping.html

Wichtig dabei ist das "cooperative" Garbage. Sobald also eine Tabelle mit alten Transaktionsdaten gelesen wird und die älteste Transaktionsid ist jünger, werden diese Daten entfernt.

Aber wie bereits geschrieben, ein regelmäßiger Backup/Restore wirkt oft wahre Wunder.
Eine ca. 70GB Datenbank wird dadurch am Wochenende in 2,5 Stunden (ca. 40 Minuten Backup, Rest Restore) wieder auf ca. 45GB reduziert.
Antworten