MySQL Datenbankintegrität gefährdet?????????
Michael Neubert
- datenbank
Hallo,
beim Einfügen von Datensätzen in eine Tabelle einer MySQL Datenbank tritt bei mir in seltenen Fällen folgende Kuriosität auf, für die ich keine Erklärung habe:
Die Tabelle besteht aus zwei Feldern (Primärschlüssel id (integer) , Name varchar). Sie sieht z.B. folgendermaßen aus (Ausgabe unter phpMyAdmin):
id Name
1 Tom
2 Klaus
3 Mike
4 Sven
5 Katja
6 Bernd
7 Micaela
Nach Einfügen eines weiteren Datensatzes kam es dann zu folgendem Effekt:
id Name
1 Tom
2 Klaus
3 Mike
8 neuer Eintrag
4 Sven
5 Katja
6 Bernd
7 Micaela
Normalerweise hätte der neue Eintrag doch in der interen Darstellung der Tabelle an das Ende der Tabelle geschrieben werden müssen (Binärbaum).
Weitere Datensätze werden dann wieder korrekt an das Ende eingefügt. Der Fehler läßt sich zwar durch ein neues Sortieren der Tabelle (alter table...) beseitigen, aber dennoch mache ich mir Gedanken, wo der Fehler liegen könnte???????????????????????????
Hat irgendjemand dafür eine Erklärung????
Danke im Vorraus :-)
Micha
Halihallo Michael
Normalerweise hätte der neue Eintrag doch in der interen Darstellung der Tabelle an das Ende der Tabelle geschrieben werden müssen (Binärbaum).
Nein. Weder ist die interne Darstellung einer Tabelle ein Binärbaum (das ist nur der
Index, nicht aber die Daten), noch ist es normal, dass neue Einträge an das Ende ge-
schreiben werden.
Weitere Datensätze werden dann wieder korrekt an das Ende eingefügt. Der Fehler läßt sich zwar durch ein neues Sortieren der Tabelle (alter table...) beseitigen, aber dennoch mache ich mir Gedanken, wo der Fehler liegen könnte???????????????????????????
Ganz einfach: Du löschst einen Datensatz, der wird intern als gelöscht markiert (braucht
jedoch immer noch Speicherplatz). Wenn du nun einen neuen Datensatz speicherst, wird
dieser nur bedingt am Ende angefügt (bedingt dann, wenn keine gelöschten Speicherstellen
vorhanden sind). Wenn jedoch ein Datensatz zuvor gelöscht wurde, nimmt der neue Datensatz
dessen Speicher in Anspruch. Ansonsten würde der Speicherverbrauch der Tabelle
explodieren.
Viele Grüsse
Philipp
Hallo Philipp,
du hast recht. Durch das Löschen/Verkleiern von Einträgen wurde Speicherplatz freigegeben. Das erklärt alles :-)
bye
Micha
Halihallo Michael
du hast recht. Durch das Löschen/Verkleiern von Einträgen wurde Speicherplatz freigegeben. Das erklärt alles :-)
Eben nicht ;)
Durch das Löschen wird kein Speicherplatz freigegeben. Aber du meintest wohl, wenn du
die Tabelle mit ALTER TABLE änderst, dann ja; wenn alle Daten sowieso geändert werden
müssen, warum dann nicht auch die gelöschten auslassen.
Aber wenn du nur an einer Speicherfreigabe interessierbar bist, solltest du wirklich
OPTIMIZE TABLE tabelle
benutzen.
Viele Grüsse
Philipp
Halihallo Michael
Normalerweise hätte der neue Eintrag doch in der interen Darstellung der Tabelle an das Ende der Tabelle geschrieben werden müssen (Binärbaum).
Weitere Datensätze werden dann wieder korrekt an das Ende eingefügt. Der Fehler läßt sich zwar durch ein neues Sortieren der Tabelle (alter table...) beseitigen, aber dennoch mache ich mir Gedanken, wo der Fehler liegen könnte???????????????????????????
Zuerst noch ein wenig mehr Ausführung, als beim ersten mal:
Wenn ein Datensatz gelöscht wird, entsteht eine "Lücke" in der Datei. Wenn es nun in
Dateien keine Lücken geben dürfte, müsste die _gesamte_ Datei (oder alles, was nach
diesem Datensatz folgt) neu geschrieben werden, du kannst dir vorstellen, dass dies bei
1'000'000 Datensätzen sehr, sehr viel Zeit kosten würde. Also hat man sich gedacht, OK,
lassen wir die Lücke doch einfach frei und speichern dort einen neuen Datensatz ab.
Dazu braucht es eine Statusangabe, die sagt: Datensatz existent oder Datensatz gelöscht.
Wenn nun ein neuer Datensatz gespeichert werden soll, wird dieser nicht einfach an das
Ende gehängt, sondern es wird erst versucht, Lücken wieder aufzufüllen (ansonsten würde
die Datei ja immer länger werden).
Es ist also keine Frage der Datenbankintegrität. Wenn du eine geordnete Liste ausgeben
willst, musst du dies über Sortierung (ORDER BY) machen, ansonsten kannst du davon
ausgehen, dass die Datensätze fern von jeglicher Logik oder Algorithmus ausgegeben
werden (Datenbanken verwalten _Mengen_ (Multi-), nicht Listen, eine "Ordnung" gibt
es nicht). Wenn du also eine geordnete Liste benötigst, _musst_ du ORDER BY verwenden.
Zudem solltest du dich mit dem Begriff des Binärbaumes (AVL-Baum! - Nicht Binär-.)
auseinandersetzen.
So, und nun hab ich noch eine Frage:
Wie wir festgestellt haben, muss es ein Status-Flag für jeden Datensatz geben, der u. a.
die Information speichert, ob der Datensatz gelöscht wurde, oder nicht. Jetzt stellt sich
mir die Frage, was wenn ein neuer Datensatz eingefügt wird? - Werden dann _alle_
Datensätze (deren Stati) eingelesen (Full Table Scan), oder gibt es für diesen Datensatz-
Status auch eine Art interner "Index"? - Wo werden diese "Status-Bytes" gespeichert,
IMHO sinnvoll wäre es gleich bei den Daten (Datensatz mit zwei SMALLINT braucht demnach
einfach 5 Bytes für die Daten, 2*2+1). Ist dies tabellentreiberspezifisch und bei jedem
anders? - Ist dieses Status-Byte indiziert? - Habe dazu in der Doku (ich hab's mal für
MySQL/ISAM gesucht) nicht's gefunden (kennt jemand die Stelle?).
Viele Grüsse
Philipp