dein code mit edit/post kann man zwar so machen, muss dann aber auch damit leben, das dabei transaktionen nicht wirklich kotrolliert committed werden
d.h. dein edit/post sorgt bei jedem schreibvorgang für einen komplett neuen kompletten blob als record version, weil nämlich zB
ein backup das du mitten drin gestartet hättest, nur genau die eine record version hätte lesen können, die zu dem Zeitpunkt
committed war. alle anderen record version die danach enstanden sind könnten ggf spätere Transaktionen noch lesen, wenn die denn irgendwo
committed wären. da du aber in einem Blob in einer Record Version pro record/column je nach pagesize bis zu 128 GB unterbringen
kannst muss firebird den kram irgendwo temporär loswerden und dabei bleibt mangels 128GB*x
RAM meistens nur das schreiben in blob
pages.
Sinngemäß erzeugt dein code in der firebird
db dafür das es record versionen alle varianten gibt.
wenn das 100000 mal durchgelaufen ist und du nirgendwo für transaction control udn auslösen garbage collection/sweep
gesorgt hast für
-in 100000 blobpages ist deine erste zeile enthalten
-in 99999 blobpages ist deine erste zeile und deine zweite zeile enthalten
-in 99998 blobpages ist deine erste zeile und deine zweite zeile und deine dritte zeile enthalten
....
solange irgendeine transaktion offen ist, kann firebird keine dieser recordversion rausschmeissen und fast jedes offene dataset hält fast immer eine transaktion offen, die den garbage collector blockiert. Und nach x durchläufen sind das nicht mehr nur eine blobpage pro record sondern gleich mehrere, daher wird die
db so groß.
Wenn du das besser machen willst, dann sorge dafür, das jeder update committed wird und du dann auch nicht noch von irgendwo anders eine
alte aktive Transaktion offen hältst (sieht man in der database statistics bzw in ibexpert auch im database monitoring).
Um die recordversionen dieses blobs aufzuräumen, die niemand mehr sehen kann, muss du Firebird einen Hinweis geben. Einfachster weg:
Mach nach deinem update/post und dem noch einzufügenden commit ein simples select count(*) from tabelle where .... mit genau dem
key, wo du gerade deine updates machst. wenn es da zum pk nämlich zB 5 Record versionen gibt, von denen nur 2 sichtbar
sind und keine zu alte transaktion das alles komplett blockiert, dann wird der garbagecollector asynchron beginnen, die nicht mehr benutzen blob pages
wieder freizugeben und diese werden dann bei späteren updates wieder benutzt.
Aber ganz im Vertrauen, nutze für sowas nicht ein select in einer request live
query, die dann per edit/post die updates bekommt. Das hat auf dataset
ebene so gruselige nebenwirkungen, die du nie wieder los wirst. wenn du was anzeigen bzw lesen willst, mach ein select, wenn du was ändern
willst, dann mach in einer anderen
query den update als update befehl mit commit und wenn dich das im client zur anzeige interessiert, was du da gerade geschrieben
hast, mach den einen neue select (viele Komponenten können da mit einer extra readonly transaction vieles automatisieren für read operationen, aber
unter high load funktioniert das nur performant, wenn du das von anfang an richtig programmierst. Das hat nichts mit Firebird zu tun, das ist bei jeder
plattform auf die eine oder andere art ähnlich.
Datasets sind nice to have für dbgrids o.ä., aber für high performance application nicht wirklich der bringer.
Unidac kann da zwar im Hintergrund einiges optimieren, aber wenn dein code sich nicht um Transaction control kümmert, können die da nicht ungefragt für sorgen, vielleicht fällt dir ja nach dem 100000. update dann ein das du doch ein rollback brauchst.
p.s.: bitte nicht hoffen das automcommit irgendwas besser macht, eigentlich sollte autocommit nicht autocommit sondern besser autostarttransaction heissen, weil es nur in ausnahmefällen für echte commits sorgt.
und wenn dich die details nicht ur dazu interessieren, in diesem videos hatte ich dazu reichlich erklärt
https://www.youtube.com/playlist?lis...0oMvOmx-wHKcCU