AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Firebird - update BLOB-Field - Datenbank wird immer größer
Thema durchsuchen
Ansicht
Themen-Optionen

Firebird - update BLOB-Field - Datenbank wird immer größer

Ein Thema von lxo · begonnen am 21. Mär 2023 · letzter Beitrag vom 22. Mär 2023
Antwort Antwort
Seite 1 von 2  1 2      
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#1

Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 15:48
Datenbank: Firebird • Version: 3 • Zugriff über: UniDAC
Hallo zusammen,

kann mir jemand erklären wieso sich das so verhält bzw. was ich machen kann damit es sich nicht so verhält.

Folgendes Problem, ich schreibe kontinuierlich etwas in einen Blob rein.
Können schon mehrere tausend Male sein.
Das führt dazu, dass sich die Datenbank irgendwann extrem schnell aufbläht.
Nach dem Backup/Restore ist sie wieder deutlich kleiner.

Ich kenn diesen Effekt bei Firebird, wenn man immer wieder Delete/Insert macht, dann wird die Datenbank größer und größer und nach einem Backup/Restore ist sie wieder kleiner.
Aber wieso tritt der Effekt bei Update auf Blob-Fields auf?

Delphi-Quellcode:
  
// Verallgemeinert, aber so in etwa schreibe ich immer wieder in das Blobfeld
var lQuery := TUniQuery.Create(nil);
  try
    lQuery.Connection := GetConnection;
    lQuery.SQL.Text := 'Select t.* from TEST t ' +
                       'Where t.ID = 1';
    lQuery.Execute;
    if not lQuery.IsEmpty then
    begin
      lQuery.Edit;
      lQuery.FieldByName( 'BLOBTEST').AsString := lQuery.FieldByName( 'BLOBTEST').AsString + sLineBreak +
                                                  Now.toString + ';' + Random(100000).ToString + ';' + Random(100000).ToString;
      lQuery.Post;
    end;
  finally
    lQuery.Free;
  end;
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#2

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 16:07
Blobs werden ja nicht im eigentlichen Record gespeichert, sondern in speziellen Pages. Daher entspricht ein Update auf ein Blob-Feld einem Insert/Delete.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#3

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 16:09
Blobs werden ja nicht im eigentlichen Record gespeichert, sondern in speziellen Pages. Daher entspricht ein Update auf ein Blob-Feld einem Insert/Delete.
Und das kann man nicht umgehen, in dem man immer wieder auf die selbe Pages schreibt?
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#4

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 16:16
Exakt das gleiche Problem habe ich mit Oracle 19c (und Db2 for i) dieses Jahr beobachtet. Oracle Tablespace, der noch ca. 10 GB Platz hat, ist nach wenigen Minuten voll. Geschrieben wurden aber nur maximal wenige MB mit einem Protokoll, immer in das gleiche DB-Feld. Der "unbenutzte", aber dennoch blockierte Tablespace kann nur durch einen Admin wieder freigemacht werden.

Eine Lösung wäre, auf normale Char-Datentypen umzustellen und das Log darin normal (Satz für Satz inserten) zu schreiben...
Michael Justin
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#5

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 16:25
Exakt das gleiche Problem habe ich mit Oracle 19c (und Db2 for i) dieses Jahr beobachtet. Oracle Tablespace, der noch ca. 10 GB Platz hat, ist nach wenigen Minuten voll. Geschrieben wurden aber nur maximal wenige MB mit einem Protokoll, immer in das gleiche DB-Feld. Der "unbenutzte", aber dennoch blockierte Tablespace kann nur durch einen Admin wieder freigemacht werden.

Eine Lösung wäre, auf normale Char-Datentypen umzustellen und das Log darin normal (Satz für Satz inserten) zu schreiben...
Da habe ich aber die Grenze von 32.767 Bytes beim Typ VARCHAR. Das reicht an der Stelle nicht.
  Mit Zitat antworten Zitat
TBx
(Administrator)

Registriert seit: 13. Jul 2005
Ort: Stadthagen
1.893 Beiträge
 
Delphi 12 Athens
 
#6

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 16:36
Wenn es sich hier tatsächlich um ein Log handelt, so würde ich das nicht in ein Blob-Feld schreiben.
Ich würde das über eine LogTabelle lösen, in der jeder Logeintrag ein Datensatz ist.
Logs in Blobfelder zu schreiben nimmt einem ja alle Auswertungsmöglichkeiten, die einem die Datenbank sonst bietet.
Thomas Breitkreuz
Gruß Thomas
- Admin DelphiPRAXIS
- Admin Delphi-Treff
- Embarcadero MVP
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#7

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 16:49
Und das kann man nicht umgehen, in dem man immer wieder auf die selbe Pages schreibt?
Das solltest du besser die Entwickler von FireBird fragen. Allerdings kannst du die gleiche Frage dann auch für das UPDATE eines normalen Record stellen. Ich gehe mal davon aus, das ist ganz tief in der Interbase/Firebird-Architektur verankert und wird wohl nicht so schnell geändert werden. Hat ja vermutlich auch was mit Transaktionssicherheit zu tun.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
lxo

Registriert seit: 30. Nov 2017
288 Beiträge
 
Delphi 12 Athens
 
#8

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 16:55
Wenn es sich hier tatsächlich um ein Log handelt, so würde ich das nicht in ein Blob-Feld schreiben.
Ich würde das über eine LogTabelle lösen, in der jeder Logeintrag ein Datensatz ist.
Logs in Blobfelder zu schreiben nimmt einem ja alle Auswertungsmöglichkeiten, die einem die Datenbank sonst bietet.
Ja, das sehe ich auch als beste Lösung.
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 21:17
Halo,
man müsste ja eigentlich den Garbage-Collector (gfix -sweep ?) anwerfen,
damit der die "alten" Blob-Pages als "kann wieder benutzt werden" markiert.

Das geht auch ohne direkten gfix-Zugriff und vor allem ohne Backup/Restore.

Es gab mal einen Artikel dazu (ibphoenix?).
Finde ich aber gerade nicht/ keine Zeit zum Suchen.
Heiko
  Mit Zitat antworten Zitat
Benutzerbild von IBExpert
IBExpert

Registriert seit: 15. Mär 2005
679 Beiträge
 
FreePascal / Lazarus
 
#10

AW: Firebird - update BLOB-Field - Datenbank wird immer größer

  Alt 21. Mär 2023, 23:25
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
Holger Klemt
www.ibexpert.com - IBExpert GmbH
Oldenburger Str 233 - 26203 Wardenburg - Germany
IBExpert and Firebird Power Workshops jederzeit auch als Firmenschulung
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 11:48 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz