Referenzierter Blödsinn

Unser täglich MySQL-Rant gib uns heute…

Ich war ja vor einiger Zeit auf einer MySQL-Schulung (siehe auch die zugehörigen Essensbilder) und zwar mit dem Ziel oder zumindest der Hoffnung, von einem “ernsthaften” MySQL-Administrator Lösungen oder zumindest Workarounds für die unzähligen, bisher bei uns aufgetretenen Unzulänglichkeiten dieses Pseudo-DBMS zu erhalten.

Leider wurden meine ob des Themas zugegebenermaßen niedrigen Erwartungen an die Schulung noch deutlich unterboten, aber wenigstens konnte ich einen wertvollen Einblick erhalten, wie Leute ticken, die mit MySQL-Consulting ihr Geld verdienen: Zu so ziemlich allen Problemen, die mein ebenfalls anwesender Kollege und ich nannten (z.B. die Unmöglichkeit, MyISAM-Dumps im laufenden Betrieb zu ziehen), lautete die hochprofessionelle Antwort, dass das halt so sei und man daran auch nichts ändern könne.

Mein absolutes Highlight war allerdings seine Aussage (inhaltlich wiedergegeben):

“Wozu braucht man denn Fremdschlüssel? Für die Konsistenz der Daten reicht es doch, wenn die zugreifenden Applikationen nur konsistente Daten an die Datenbank liefern. Eine Prüfung der referentiellen Integrität in der Datenbank verbraucht doch nur unnötig Zeit!”

Ich lass das einfach mal unkommentiert so stehen, erinnere aber nochmal daran, dass der Herr sein Geld mit Datenbankconsulting (nagut, MySQL-Consulting) verdient…

Anyway, heute wurde mir dieses Zitat noch einmal in Erinnerung gerufen, als ich vor dem Problem stand, dass sich ein frisch gezogener MySQL-Dump nicht in eine jungfräuliche MySQL-Datenbank einspielen ließ (ziemlich genau das hier beschriebene Problem mit der Universalfehlermeldung “ERROR 1005 (HY000)”).

Das grundsätzliche Problem besteht darin, dass gleich am Anfang des Dumps die Anlage der Tabellen und der Fremdschlüssel synchron erfolgt (jeweils alles in einem CREATE-TABLE-Statement). Dadurch existieren jedoch zu etlichen, frisch definierten Schlüsseln die referenzierten Tabellen (noch) nicht, so dass infolgedessen das gesamte CREATE TABLE fehlschlägt. (Kurz bei Postgres vorbeigeschaut: Bei pgdump werden im Dumpfile erst die Tabellen ohne Schlüssel angelegt, dann die Tabellen gefüllt und erst zum Ende die Fremdschlüsselbeziehungen definiert und dabei natürlich auch geprüft).

Nun gibt es aber auch für dieses Problem eine MySQL-Lösung, deren schlichte Existenz einen DBA zum Schreien bringen sollte: Man kann in MySQL die gesamte Prüfung der referentiellen Integrität abschalten!!!!!111elf.

Und zwar so richtig abschalten. Richtig im Sinne von: auch wenn die referentielle Integrität wieder aktiviert wird, führt dies nicht zu einer Prüfung, ob die Datenbank überhaupt noch in einem konsistenten Zustand ist!

Kleines Beispiel zum Gruseln:

Wir legen zwei Tabellen an, wobei die zweite die erste via Fremdschlüssel referenziert:

mysql> create table foo (a int not null, PRIMARY KEY(a) );
Query OK, 0 rows affected (0.02 sec)
mysql> create table bar (b int, FOREIGN KEY (b) REFERENCES foo (a));
Query OK, 0 rows affected (0.01 sec)

Ein Einfügen von Werten in foo ist generell unproblematisch, in bar sind hingegen nur Werte erlaubt, die schon in foo stehen:

mysql> insert into foo values (1);
Query OK, 1 row affected (0.01 sec)
mysql> insert into bar values (1);
Query OK, 1 row affected (0.00 sec)
mysql> insert into bar values (0);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`mytest`.`bar`, CONSTRAINT `bar_ibfk_1` FOREIGN KEY (`b`) REFERENCES `foo` (`a`))

Und nun kommt’s:

mysql> set foreign_key_checks = 0;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into bar values (0);
Query OK, 1 row affected (0.00 sec)
mysql> set foreign_key_checks = 1;
Query OK, 0 rows affected (0.00 sec)

Und ja, die Daten sind wirklich drin:

mysql> select * from bar;
+------+
| b |
+------+
| 0 |
| 1 |
+------+
2 rows in set (0.00 sec)

Wer noch mehr schlechte Laune braucht, kann sich mal das MySQL-Handbuch zum Thema “Fremdschlüssel-Beschränkungen” zu Gemüte führen. Darin sind solche Perlen enthalten wie:

Abweichung von SQL-Standards: Ein FOREIGN KEY-Constraint, der einen Nicht-UNIQUE-Schlüssel referenziert, ist nicht Standard-SQL, sondern eine InnoDB-Erweiterung dieses Standards.

oder

Hinweis: Trigger werden von kaskadierenden Fremdschlüsselaktionen derzeit nicht aktiviert.

So, Feierabend, mir reicht’s für heute…

2 thoughts on “Referenzierter Blödsinn”

  1. ROFL!

    Wozu braucht man Gerichte? Für den sozialen Frieden reicht es doch aus, wenn sich alle an die Gesetze halten! 😉

    Das mit dem FOREIGN-KEY-Constraint, der einen Nicht-UNIQUE-Key referenziert, ist auch ein Schenkelklopfer!

  2. Erschreckend. Besonders auch, dass man die Prüfung auf Konsistenz anscheinend noch nicht einmal manuell auslösen kann. Jedenfalls habe ich auf die Schnelle nichts dazu gefunden. Da kann man sich ja dann selbst ein paar SQL-Queries zu basteln.

Comments are closed.