Entfernen Sie die DEFINER-Klausel aus MySQL Dumps


114

Ich habe einen MySQL-Speicherauszug einer meiner Datenbanken. Darin gibt es DEFINER-Klauseln, die aussehen wie:

"DEFINER=`root`@`localhost`" 

Diese DEFINER-Klauseln befinden sich nämlich in meinen Anweisungen CREATE VIEW und CREATE PROCEDURE. Gibt es eine Möglichkeit, diese DEFINER-Klauseln aus meiner Dump-Datei zu entfernen?


Ein Fehler wurde vor Jahren gemeldet, aber er sieht verlassen aus: bugs.mysql.com/bug.php?id=24680
1234ru

Antworten:


109

Ich glaube nicht, dass es eine Möglichkeit gibt, das Hinzufügen von DEFINERs zum Dump zu ignorieren . Es gibt jedoch Möglichkeiten, sie zu entfernen, nachdem die Speicherauszugsdatei erstellt wurde.

  1. Öffnen Sie die Dump-Datei in einem Texteditor und ersetzen Sie alle Vorkommen von DEFINER=root@localhostdurch eine leere Zeichenfolge ""

  2. Bearbeiten Sie den Speicherauszug (oder leiten Sie die Ausgabe weiter) mit perl:

    perl -p -i.bak -e "s/DEFINER=\`\w.*\`@\`\d[0-3].*[0-3]\`//g" mydatabase.sql
  3. Leiten Sie den Ausgang durch sed:

    mysqldump ... | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > triggers_backup.sql

1
@FastTrack, bitte entfernen Sie die gesamte Zeichenfolge.
Abhay

3
Ich schlage vor zu erwähnen, dass DEFINER nicht entfernt, sondern wie folgt auf CURRENT_USER gesetzt werden kann: sed -E 's/DEFINER=[^ ]+@ [^] + /DEFINER=CURRENT_USER/g' dump.sql > new_dump.sqlEs hat den Vorteil, Einschränkungen / Zugriffskontrolle beizubehalten .
4thfloorstudios

27
Der sedBefehl entfernt die DEFINER-Klausel nicht aus Prozeduren und Funktionen. Hier ist die erweiterte Version, die Ansichten, Trigger, Prozeduren und Funktionen behandelt: sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*PROCEDURE/PROCEDURE/' | sed -e 's/DEFINER[ ]*=[ ]*[^*]*FUNCTION/FUNCTION/'
Vladimir Strugatsky

4
Zu Ihrer Information --- obwohl dies zum Zeitpunkt dieser Antwort nicht der Fall war, wird MySQL> 5.6 jetzt mit einem mysqldump (1) ausgeliefert, der optional "--skip-definer" unterstützt: dev.mysql.com/doc/refman /5.7/de/…
Kevin_Kinsey

4
Nein, es ist nicht mysqldump, sondern mysql p ump, der --skip-definer hat.
Xdg

70

Sie können mit SED entfernen

sed -i 's/DEFINER=[^*]*\*/\*/g' mydump.sql

In MacOS:

sed -i '' 's/DEFINER=[^*]*\*/\*/g' mydump.sql

Was ist hier in MacOS los, um anders zu sein?
Alex

1
In der Manpage für sed on mac heißt es: -i extension"Bearbeiten Sie Dateien direkt und speichern Sie Sicherungen mit der angegebenen Erweiterung. Wenn eine Erweiterung mit der Länge Null angegeben wird, wird keine Sicherung gespeichert. Es wird nicht empfohlen, eine Erweiterung mit der Länge Null anzugeben, wenn direkte Bearbeitung von Dateien, da Sie in Situationen, in denen der Speicherplatz erschöpft ist, Beschädigungen oder teilweise Inhalte riskieren usw. "
Chad

Schön das zu wissen, @Chad. Ich benutze sed wie dieses in Mac seit mehr als 5 Jahren. Ich hatte nie Probleme mit Speicherplatz oder beschädigten Dateien. Aber natürlich ist etwas zu beachten. Danke fürs klarstellen.
Ricardo Martins

Ich bin auch auf Mac nie auf diese Probleme gestoßen. Ich dachte nur, ich würde das klarstellen, da @Alex gefragt hat :)
Chad

57

Seit MySQL-Version 5.7.8 können Sie die --skip-definerOption mit MySQL-Pumpe verwenden, z.

mysqlpump --skip-definer -h localhost -u user -p yourdatabase

Siehe das aktualisierte MySQL-Handbuch unter http://dev.mysql.com/doc/refman/5.7/en/mysqlpump.html#option_mysqlpump_skip-definer


8
Für alle, die sich fragen , was der Unterschied zwischen mysqldumpund ist mysqlpump- hier ist eine verwandte Frage: dba.stackexchange.com/questions/118846/mysqldump-vs-mysqlpump
Scadge

Ich habe phpMyAdmin und MySQL Workbench installiert. Wie führe ich diesen Befehl unter Windows aus?
Posfan12

(nach einigen Tests: -1) Es verwendet information_schema.user, und dies ist nicht immer für alle Benutzer lesbar
bato3

17

Ich habe diese Ideen verwendet, um die DEFINER-Klausel aus meiner eigenen mysqldump-Ausgabe zu entfernen, aber ich habe einen einfacheren Ansatz gewählt:

Entfernen Sie einfach das !vor dem Code und DEFINER, und der Rest des Kommentars wird zu einem regulären Kommentar.

Beispiel:

/*!50017 DEFINER=`user`@`111.22.33.44`*/

ist hilflos gemacht, so wenig wie dies zu tun ..

/* 50017 DEFINER=`user`@`111.22.33.44`*/

Der einfachste reguläre Ausdruck ist jedoch das Entfernen des! und die Zahlen

mysqldump | /usr/bin/perl -pe 's/\!\d+ DEFINER/DEFINER/' > dumpfile.sql

Das entfernt !#### DEFINERund ersetzt durch DEFINER ... Sie könnten DEFINER auch entfernen, es spielt keine Rolle - sobald das "!" ist weg


16

Nach den Empfehlungen des anderen finden Sie hier ein Beispiel für das Entfernen des DEFINER aus dem Speicherauszug, nachdem der Speicherauszug beendet wurde:

mysqldump -u user --password='password' -h localhost database | grep -v "50013 DEFINER" > dump.sql

4
Bei Triggern sehen die Zeilen wie folgt aus: / *! 50003 CREATE * / / *! 50017 DEFINER = user@ localhost* / / *! 50003 Trigger my_triggername BEVOR INSERT ON my_table FÜR JEDE REIHE .... * / ;; und grep -vwird diese Zeilen vollständig löschen. (obwohl 50017! = 50013)
Kenney

13

Wie andere bereits erwähnt haben, ist es nicht allzu komplex, den Definierer mit einem regulären Ausdruck zu entfernen. Aber die anderen Beispiele haben mir die Ansichtsdefinitionen entzogen.

Dies ist der reguläre Ausdruck, der für mich funktioniert hat:

sed -e 's/DEFINER=[^ ]* / /'

Und schneller ^^ Danke
Kevin Labécot

1
Funktioniert nicht mit Triggern - entfernt auch die */. MySQL 5.6.31.
Franc Drobnič

10

Für eine automatisierte Lösung könnten Sie sich ansehen mysqlmigrate. Es ist ein Bash-Wrapper mysqldump, mit dem Sie Datenbanken migrieren und die DEFINER-Anweisungen ignorieren können. Beispiel:

$ mysqlmigrate -u root -p pass --ignore-definer from_db to_db

http://thesimplesynthesis.com/post/mysqlmigrate (oder GitHub )

Andernfalls ist ein Befehl wie Abhay erforderlich:

$ mysqldump -u root -ppass the_db | sed -e 's/DEFINER[ ]*=[ ]*[^*]*\*/\*/' > the_db.sql

6

Eine weitere Option unter OSX zum Entfernen von Definierern in der Datei:

sed -i '' 's/DEFINER=`[^`][^`]*`@`[^`][^`]*`//g' file.sql

5

Sie sollten die Antwort hier: /dba/9249/how-do-i-change-the-definer-of-a-view-in-mysql/29079#29079

Der beste Weg, um dieses Problem zu beheben, besteht meiner Meinung nach darin, keine zusätzliche Analyse von Zeichenfolgen mit sed oder grep oder einer anderen zu erstellen. Stattdessen kann mysqldump durch Hinzufügen von --single-transaction einen guten Speicherauszug generieren


Warum herabgestimmt? Warum wird diese Antwort nicht als nützlich angesehen?
Jose Nobile

1
Ihre Antwort benötigt noch ungefähr 90 Upvotes, um die Position zu erhalten, die sie verdient. Sie haben meine :)
Patrick van Bergen

4

Eine schnelle Möglichkeit, dies zu tun, besteht darin, die Ausgabe von mysqldump durch sed zu leiten , um die DEFINERin bedingten Kommentaren eingeschlossenen Anweisungen zu entfernen . Ich verwende dies, um DEFINERaus CREATE TRIGGERAnweisungen zu entfernen , aber Sie können die Versionsnummer des Bedingungskommentars im regulären Ausdruck an Ihre Zwecke anpassen.

mysqldump -u user --password='password' -h localhost database | \
  sed 's/\/\*!50017 DEFINER=`.*`@`.*`\*\///' 

1
Eine etwas besser lesbare sed-Anweisung: sed "s / DEFINER (. *?) FUNCTION / FUNCTION /"
reustmd

4

Ich bin mir nicht sicher, ob es hilft, aber ich verwende SQLyog Community Edition, verfügbar unter: -

https://code.google.com/p/sqlyog/wiki/Downloads

Wenn Sie SQL sichern oder in eine andere Datenbank kopieren, können Sie DEFINER ignorieren.

Es ist kostenlos und bietet die grundlegenden Funktionen, die viele Menschen benötigen

Es gibt auch eine kostenpflichtige Version von: -

https://www.webyog.com/product/sqlyog

Prost


Anstatt nur als "nicht nützlich" zu kennzeichnen, wäre es vielleicht nützlicher, wenn Sie antworten, warum Sie der Meinung sind, dass dies nicht nützlich ist.
Itfidds

3

Für mich funktioniert das : perl -p -i.bak -e "s/DEFINER=[^ |\s]*//g" yourdump.dmp. Dadurch wurde DEFINER = root @ localhost bei jeder Erstellung einer Prozedur aus meinem Speicherauszug entfernt


2

Hier ist eine vollständige funktionierende Lösung zum Entfernen von DEFINER-Informationen für MySQL 5.6.xund Linux (getestet am CentOS 6.5).

Normalerweise müssen wir die folgenden Einträge aus dem MySQL-Dump ersetzen (wenn sie zusammen mit Daten und Triggern / Routinen / Funktionen verwendet werden).

/*!50013 DEFINER=`MYSQLUSER`@`localhost` SQL SECURITY DEFINER */
/*!50013 DEFINER=`MYSQLUSER`@`%` SQL SECURITY DEFINER */
CREATE DEFINER=`MYSQLUSER`@`%` PROCEDURE `PROCEDURENAME`(
CREATE DEFINER=`MYSQLUSER`@`localhost` PROCEDURE `PROCEDURENAME`(
CREATE DEFINER=`MYSQLUSER`@`%` FUNCTION `FUNCTIONNAME`(
CREATE DEFINER=`MYSQLUSER`@`localhost` FUNCTION `FUNCTIONNAME`(
/*!50003 CREATE*/ /*!50017 DEFINER=`MYSQLUSER`@`%`*/ /*!50003 TRIGGER `TRIGGERNAME`
/*!50003 CREATE*/ /*!50017 DEFINER=`MYSQLUSER`@`localhost`*/ /*!50003 TRIGGER `TRIGGERNAME`

Der Dump wurde mit dem folgenden Befehl mysqldump erstellt.

mysqldump -uMYSQLUSER -pPASSWORD DATABASENAME -R > dbdump.sql

Die erforderliche Dump-Datei ohne DEFINER-Informationen kann mit den folgenden drei Befehlen abgerufen werden.

Command-1    
sed -i 's|DEFINER=[^*]*\*|\*|g' [PATH/]dbdump.sql

Command-2
find -name [PATH/]dbdump.sql | xargs perl -pi -e "s/ DEFINER=\`MYSQLUSER\`@\`localhost\`//"

Command-3
find -name [PATH/]dbdump.sql | xargs perl -pi -e "s/ DEFINER=\`MYSQLUSER\`@\`%\`//"

Wenn sich die Dump-Datei in Ihrem aktuellen Ordner befindet, ignorieren Sie [PATH /].

Wenn die Daten in Tabellen sehr groß sind, nehmen Sie den Speicherauszug in zwei Dateien, in einer Speicherauszugsdatei den Speicherauszug mit Daten und in einer anderen Speicherauszugsdatei nur den Speicherauszug der Skripte (Trigger / Funktionen / Prozeduren) und führen Sie die obigen drei aus Befehle in der 2. Dump-Datei (Skripte).


1

Ersetzen Sie alle Ihre Definierer-Benutzer durch CURRENT_USER. In meinem Gradle-Skript, das das Backup erstellt, sieht mein Ersetzungsskript folgendermaßen aus:

ant.replaceregexp(file: "$buildDir/sql/setupDB.sql", match: "`${project.ext.prod_db_username}`@`%`", replace: "CURRENT_USER", byline: true);

Das heißt wirklich nur ANT. Dann müssen Sie sich keine Sorgen machen.


1

Auf Linux-Computern können Sie diesen Einzeiler verwenden:

mysql -uuser -ppwd -A --skip-column-names -e"SELECT CONCAT('SHOW CREATE VIEW ',table_schema,'.',table_name,';') FROM information_schema.tables WHERE engine IS NULL and table_schema like 'mydb%'" | mysql -uuser -ppwd -A --skip-column-names | sed -rn 's/.*?VIEW ([^\s]+?) (AS .*?)\s([^\s]+?)\s([^\s]+?)/DROP VIEW \1;\nCREATE VIEW \1 \2;/p' | mysql -uuser -ppwd -A --skip-column-names

Sie müssen nur fett gedruckte Zeichenfolgen durch Ihre DB-Benutzeranmeldeinformationen und das Datenbanknamen- / Like-Muster ersetzen.

Weitere Informationen hier: http://blog.novoj.net/2014/05/16/recreate-mysql-views-without-definer-one-liner-solution-linux/


1

Der einzige Weg, wie ich es unter Windows zum Laufen bringen kann:

Installieren Sie http://gnuwin32.sourceforge.net/ haben sed in der Befehlszeile , und fügen Sie den Windows - Pfad ein : D: \ Programme \ GetGnuWin32 \ ist;

sed -i "s|DEFINER=`mydbuser`@`%%` SQL SECURITY DEFINER||g" "D:/prod_structure.sql"

sed -i "s|DEFINER=`mydbuser`@`%%`||g" "D:/prod_structure.sql"

mysqldump -P{port} -h{host} -u{user} -p{password} --routines --no-data --lock-tables=false database_prod > D:\prod_structure.sql

1

Vielen Dank für die Hinweise. Da ich faul bin, habe ich ein Skript mit dem Namen "MYsqldump" geschrieben:

DB=$1
HOST=$2
USER=$3
MYSQLDUMP='/usr/bin/mysqldump'
PARAMS="--complete-insert --disable-keys=0 --extended-insert=0 --routines=0 --skip-comments"
DAY=`date +%d`
MONTH=`date +%m`
YEAR=`date +%Y`
FILE=$DB.$DAY-$MONTH-$YEAR.sql

    if (( $# < 3 )) ; then
        echo ""
        echo "usage: MYsqldump <db> <host> <user>"
        echo ""
        exit 1
    fi

    $MYSQLDUMP -h $HOST -u $USER -p  $PARAMS $DB | grep -v '/*!50013 DEFINER' > $FILE

1

Für so etwas wie:

DELIMITER ;;
CREATE DEFINER = `mydb` @` localhost` FUNCTION `myfunction` () RETURNS int (11)
Start
(...)
Ende ;;

Versuche dies:

mysqldump --force --routines --opt --user = myuser --databases mydb | sed -es / DEFINER = `. *` @ `. *` \ // g '

1
  1. Öffnen Sie Ihre Datenbank mit einem beliebigen Editor, den ich mit Notepad ++ verwendet habe.

  2. Finde alle teste das DEFINER=root@localhost und ersetze es durch nichts ( "") IE. Lösche es.

Anschließend können Sie es auf einen beliebigen Host importieren.


0

Der einfachste reguläre Ausdruck, der für mich mit allen Objekten funktioniert, ist:

sed 's/DEFINER=[^ ]*`//' ...

Beachten Sie, dass dies sein quote-namesmuss TRUE(was standardmäßig der Fall ist).

Hoffe, dass in neueren Versionen der --skip-definerin mysqlpump in Version 5.7 eingeführte Schalter auch zu mysqldump kommt.


0

Ich habe das PowerShell-Skript verwendet, um alle Zeilen zu entfernen mit DEFINER:

get-content $ file_in_full_path | select-string -pattern $ line_string_delete -notmatch | Out-File-width 1000000000 -Encoding Default $ file_out_full_path


0

Da für mich nichts funktionierte, musste ich meinen eigenen regulären Ausdruck schreiben.

  1. Versuchen Sie, Ihre Datenbank in eine Datei, eine catganze Datei und grepnur Ihre Definiereranweisungen zu speichern, um sie anzuzeigen.

    cat file.sql | grep -o -E '. {, 60} DEFINER. {, 60}'

  2. Schreiben Sie Ihre Regex

  3. Pipe deine Müllkippe mit diesem Regex in sed. Zum Beispiel lautet meine Aussage:

    mysqldump | sed -Es // *! 500 [0-9] [0-9] DEFINER =. +? * /// '| sed -Es / DEFINER = ?[^ ]+?? @ ?[^ ]+?? // '

  4. Profitieren!


0

remove_definers.bat:

@echo off
(for /f "tokens=1,2*" %%a in (dumpfile.sql) do (
 if "%%b"=="" (echo %%a) else (
  echo %%b | find "DEFINER" > null && echo %%a %%c || echo %%a %%b %%c
 )
)) > dumpfile_nodefiners.sql
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.