Fatal error: Uncaught mysqli_sql_exception: The user specified as a definer (''...@'...') does not exist in...
Jörg
- php
Hallo,
ich nutze seit graumer Zeit das von Raketenskripter aka Raketenwilli geschriebene Script, um nächtlich meine Datenbanken zu sichern. Danke nochmal für das tolle Script! 👍
Das Script läuft tadellos und damit ich im Falle des Falles hieraus gezogen Backups schnell und unkompliziert einspielen kann, habe ich mir eine bequeme Api geschrieben, die das vorzüglich macht. Der Konsolenbefehl lautet dann:
Konsolenbefehl zum Einspielen der Datenbank
/bin/gunzip -c /mein/pfad/zum/dump/2023-05-02/2023-05-02_01:59:01_myDB.sql.gz | grep -vP "^USE \`myDB\`;$" | /usr/bin/mysql -u myDB-kopie -p'myPass!' -h localhost -B myDB-kopie
Nun habe ich die Api dahin gehend erweitert, mir auch einen Shellbefehl zu generieren, der mir ein beliebiges Backup in meine lokale Xamppinstallation einspielt, auch das funktioniert eingentlich sehr gut. Die DB wird anstandslos eingespielt.
/bin/gunzip -c /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB.sql.gz | grep -vP "^USE \`myDB\`;$" | /mnt/d/myXampp8/mysql/bin/mysql -u root -p -h localhost myDBname
Klappt hervorragend, die DB wird eingespielt.
Aber beim Arbeiten mit der DB wird folgedender Fehler erzeugt:
Fatal error: Uncaught mysqli_sql_exception: The user specified as a definer ('...'@'....de') does not exist in D:\myXampp8\htdocs\testverz\script.php:601
Wo setze ich an?
Kann ich diesen User aus der *.sql.gz mit einem weiteren Konsolenbefehl nicht zuvor löschen oder ersetzen?
Jörg
Hallo Jörg,
du hast den User rausgepunktet.
Nehmen wir mal an, da hätte
as a definer ('foo'@'example.org') does
gestanden.
Würde es denn den User foo@example.org geben? Irgendwie muss er ja an diese Definer-ID herangekommen sein und ich kann mir vorstellen, dass da im Script Hochkommas sind, wo keine hingehören und sie dann in der DB landen, statt nur Strings zu begrenzen.
Rolf
Hallo Rolf,
Nehmen wir mal an, da hätte
as a definer ('foo'@'example.org') does
gestanden.
Würde es denn den User foo@example.org geben? Irgendwie muss er ja an diese Definer-ID herangekommen sein und ich kann mir vorstellen, dass da im Script Hochkommas sind, wo keine hingehören und sie dann in der DB landen, statt nur Strings zu begrenzen.
Den User würde es auf dem Produktivserver geben, aber natürlich in meinem XAMPP nicht.
Daher würde ich gerne den Dump so bearbeiten, dass es den User dort im Dump auch nicht mehr gibt, bevor ich ihn in mein XAMPP importiere.
Jörg
Ich habe gerade mal meine Trigger entfernt und schopn lässt sich mit den Daten arbeiten.
Es muss also an den Triggern liegen, aber inwiefern?
Sind die auf einen DB-User registriert?
Und wenn ja, wie reagiere ich darauf?
Jörg
Sind die auf einen DB-User registriert?
Habe gerade mal einen Dump geöffnet und die Trigger sind dort so vermerkt:
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`DB555555`@`server%.example.com`*/ /*!50003 TRIGGER `myTriggerName` AFTER INSERT ON `tableA`
FOR EACH ROW BEGIN
INSERT INTO ...
SET
...
Erstelldatum = now();
END */;;
DELIMITER ;
Es muss also an den Triggern liegen, aber inwiefern?
Naja. Wie es scheint liegt es aber an den Daten im Dump.
Wenn Du auf dem Zielserver Benutzer nicht willst, die Du auf dem Quellserver hast, die dann aber in Triggern als creator werden (woran Rechte hängen), dann geht das notwendig in die Hose.
Lösung:
Jage den Dump durch etwas wie sed. Ersetze dabei den creator des Triggers durch einen existierenden user:
Test: (Datei: test.txt)
Holla.
Da steht 'foo'@'bar.de' drin. Wirklich 'foo'@'bar.de'.
Aktion
$ sed -e "s/'foo'@'bar.de'/'bar'@'foo.org'/g" test.txt > text.neu;
Ausgabe:
$ cat text.neu
Holla.
Da steht 'bar'@'foo.org' drin. Wirklich 'bar'@'foo.org'.
Hallo Raketenwilli,
Es muss also an den Triggern liegen, aber inwiefern?
Naja. Wie es scheint liegt es aber an den Daten im Dump.
Ja klar, stimmt.
Es liegt daran, dass die Trigger in meinem XAMPP automatisch auf root@localhost als Definer angelegt werden.
keine Ahnung, wo mysql abspeichert, dass die eigentlich auf einen anderen Definer laufen sollten.
Wenn Du auf dem Zielserver Benutzer nicht willst, die Du auf dem Quellserver hast, die dann aber in Triggern als creator werden (woran Rechte hängen), dann geht das notwendig in die Hose.
Verstehe.
Lösung:
Jage den Dump durch etwas wie sed. Ersetze dabei den creator des Triggers durch einen existierenden user:
Test: (Datei: test.txt)
Holla. Da steht 'foo'@'bar.de' drin. Wirklich 'foo'@'bar.de'.
Aktion
$ sed -e "s/'foo'@'bar.de'/'bar'@'foo.org'/g" test.txt > text.neu;
Ja, genau an sowas dachte ich, danke! 👍
Kann ich auch den gepackten dump gleich durch sed jagen und danach, wenn erfolgreich, gleich importieren, also so in der Art?
gunzip -c /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB.sql.gz | sed -e "s/'foo'@'bar.de'/'bar'@'foo.org'/g" | gzip > /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB_neu.sql.gz && /mnt/d/myXampp8/mysql/bin/mysql -u root -p -h localhost myDBname < /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB_neu.sql.gz
Jörg
Kann ich auch den gepackten dump gleich durch sed jagen und danach, wenn erfolgreich, gleich importieren, also so in der Art?
gunzip -c /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB.sql.gz | sed -e "s/'foo'@'bar.de'/'bar'@'foo.org'/g" | gzip > /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB_neu.sql.gz && /mnt/d/myXampp8/mysql/bin/mysql -u root -p -h localhost myDBname < /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB_neu.sql.gz
Oder in meinem Fall:
gunzip -c /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB.sql.gz | sed -E "s/DEFINER=\`[^`]+\`@\`example\.com\`/DEFINER=\`root\`@\`localhost\`/g" > /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB_neu.sql && \
gzip /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB_neu.sql && \
/mnt/d/myXampp8/mysql/bin/mysql -u root -p -h localhost myDBname < /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB_neu.sql.gz
oder vielleicht auch direkt ohne den Zwischenschritt des Speicherns in einer neuen Datei?
gunzip -c /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB.sql.gz | sed -E "s/DEFINER=\`[^`]+\`@\`example\.com\`/DEFINER=\`root\`@\`localhost\`/g" | mysql -u root -p -h localhost myDBname
Passt das?
Und lieber in einem Schritt oder mit Zwischenschritt?
Jörg
gunzip -c /home/thatsMe/import_db/2023-05-02/2023-05-02_01:59:01_myDB.sql.gz | sed -E "s/DEFINER=\`[^`]+\`@\`example\.com\`/DEFINER=\`root\`@\`localhost\`/g" | mysql -u root -p -h localhost myDBname
Bei sed stürzt mein Linux ab, ich vermute mal, dass es an Arbeitsspeicher fehlt oder die Datei einfach mit fast einem GB zu groß ist.
Mit awk geht es aber:
gunzip -c /mein/pfad/zum/dump/test.sql.gz | awk '{gsub(/DEFINER=`[^`]+`@`example\.com`/, "DEFINER=`root`@`localhost`")}1' | grep -vP "^USE \`myDB\`;$" | /mnt/d/xampp8/mysql/bin/mysql.exe -u root -p -h localhost myDBname
Danke für die Hilfe und Gruß,
Jörg
Danke für die Hilfe
Bitte. Gern geschehen. (Und entschuldige mein Mittagschläfchen…)
Danke für die Hilfe
Bitte. Gern geschehen. (Und entschuldige mein Mittagschläfchen…)
Gar kein Problem, Du hast mich auf die richtige Fährte gebracht, da ist dann ein Mittagsschläfchen nicht mehr als verdient. 😉
Jörg
Hello Jörg,
bevor Du dir über die Skripte Gedanken machst, solltest Du dir nochnals über die Rahmenbedingungen klar werden.
Ich beschäftige mich seit ca. 20 Jahren mit diesen Aufgabenstellungen und poste hier öfter Beschreibungen meiner (wenigen) Problemfälle bzw. Museumshosts. Das wird dann von einigen Mitlesern oft so verstanden, als wären da keine neuen Erkenntnisse. Leider sind erfahrungsgemäß die meisten Hosts älter (manchmal bewahrt einen das aber auch vor neuen Lücken).
Fastix aka Rakete* unterstützt mich seitdem wirklich gut mit innovativen Ideen und diversen Lösungen.
Allerdings kann auch er nicht raten, welche Möglichkeiten Du außer den beschriebenen noch hättest, um deiner Aufgabenstellung im Detail gerecht werden zu können.
Die Fragen von
sind also immer als erstes zu klären.
Glück Auf
Tom vom Berg
Hallo Tom,
immer auf dem Boden bleiben.
Es wird nächtlich ein Dump jeder DB gesichert.
Es geht nur ums Wiedereinlesen und das nicht auf dem server, denn das klappt ganz vorzüglich.
Es geht nur darum, dass ich ab und an gerne zum lokalen testen eine DB auf mein XAMPP einspielen möchte. Habe ich bisher über Einspielen auf dem server und anschließendem Kopieren der DB auf mein XAMPP gemacht. Klappt.
Aber bequemer wäre es natürlich, den S`Dump ohne Umweg gleich ins XAMPP zu importieren, der befehl dafür liegt vor und funktioniert auch vorzüglich.
Lediglich kann ich mit den Daten nicht arbeiten, weil die "userbehaftet" sind und es diesen User verstädlicherweise auf meinem XAMPP nicht gibt.
Es geht bei meiner Frage also wirklich lediglich darum, den Dump nachträglich vom User abzutrennen.
Jörg
bevor Du dir über die Skripte Gedanken machst, solltest Du dir nochnals über die Rahmenbedingungen klar werden.
- was wird gefordert?
-- dynamische Sicherung ggf. auch während des Betriebs?
-- Vollsicherung mit Offtime des Datenbankservers- wie kann ich das erreichen?
- welche Nachteile hat welche Lösung?
- Wie unterstützt mich das Datenbanksystem dabei?
- Wie unterstützen mich das Filesystem und das Betriebssystem dabei?
- Wo wird gesichert?
-- im LAN
-- Über das WAN, also z. B. bei mir zuhause?- Wie hoch ist die Busgeschwindigkeit zwischen lokalen Permanentspeichern?
- Wie hoch ist die Transfergeschwindigkeit im LAN oder WAN (Internet)?
Ich beschäftige mich seit ca. 20 Jahren mit diesen Aufgabenstellungen und poste hier öfter Beschreibungen meiner (wenigen) Problemfälle bzw. Museumshosts. Das wird dann von einigen Mitlesern oft so verstanden, als wären da keine neuen. Leider sind werfahrungsgemäß die meisten Hosts älter (manchmal bewahrt einen das aber auch vor neuen Lücken).
Fastix aka Rakete* unterstützt mich seitdem wirklich gut mit innovativen Ideen und diversen Lösungen.
Allerdings kann auch er nicht raten, welche Möglichkeiten Du außer den beschriebenen noch hättest, um deiner Aufgabenstellung im Detail gerecht werden zu können.
Die Fragen von
- möglicher Offtime
- mittlerer Übertragungskapatzität (egal ob lokal oder per WAN/GAN)
sind also immer als erstes zu klären.
Hello Jörg,
immer auf dem Boden bleiben.
Ok, ich bin draußen.
Du darfst aber gerne später nochmal nachfragen, wenn Du erkannt hast, dass Du viel zu tief einsetzt.
Glück Auf
Tom vom Berg
immer auf dem Boden bleiben.
Ok, ich bin draußen.
Einverstanden. 👍
Lieber Jörg,
wenn ich einen gezippten SQL-Dump auf meinem localhost einspielen will, verwende ich das hier:
unzip -p Downloads/meine_db.sql.zip | mysql -u root -p meine_db
Zur Erklärung: Nach dem Entpacken wird der Inhalt mit dem Pipe-Symbol an ein anderes Programm weiter gereicht, in diesem Fall das Kommandozeilen-Programm mysql. Dieses erhält mit dem -u
-Schalter einen Benutzernamen (hier root) und mit dem -p
-Schalter die Aufforderung, das Passwort einzufordern, welches ich dann eintippen muss.
Wenn Du das Eintippen des Passwortes wegautomatisieren willst, weil Du die Backups automatisch einspielen willst, dann braucht es dafür Tricks mit echo
und so.
Liebe Grüße
Felix Riesterer