Wie kann ich die Berechtigungen aus MySQL exportieren und dann auf einen neuen Server importieren?

88

Ich kann die Datenbanken mit mysqldump exportieren / importieren und das ist in Ordnung, aber wie erhalte ich die Berechtigungen für den neuen Server?

Für zusätzliche Punkte gibt es bereits einige bestehende Datenbanken auf der neuen. Wie importiere ich die alten Server-Privilegien, ohne die bestehenden zu beschädigen?

Alter Server: 5.0.67-Community

Neuer Server: 5.0.51a-24 + lenny1

BEARBEITEN: Ich habe einen Speicherauszug der Datenbank "mysql" vom alten Server und möchte nun wissen, wie die Datenbank "mysql" auf dem neuen Server ordnungsgemäß zusammengeführt werden kann.

Ich habe einen direkten 'Import' mit phpMyAdmin versucht und einen Fehler bezüglich eines Duplikats erhalten (eines, das ich bereits manuell migriert habe).

Hat jemand eine elegante Möglichkeit, die beiden 'mysql'-Datenbanken zusammenzuführen?

Gareth
quelle
1. Müssen Sie PHPMyAdmin verwenden? Wenn ja, schreibe ich einige PHPMyAdmin-spezifische Anweisungen für Sie. 2. In PHPMyAdmin, wenn Sie versuchen, "* aus mysql.user limit 1" auszuwählen. Erhalten Sie Ergebnisse oder einen Fehler?
Bruno Bronosky
1
Wie ich weiter unten erwähnte, ist Richards mygrants-Skript ein guter Weg, um Grant-Informationen zu erhalten. Sie können jedoch auch versuchen, die Sicherungsdatei zu bearbeiten, um INSERTs für Benutzer, die bereits vorhanden sind, in die Benutzertabelle zu kommentieren. Die vom alten Server wiederhergestellten Berechtigungen für die Datenbank werden dann kopiert. Wenn Sie Berechtigungen für einige der in der neuen Box wiederhergestellten Datenbanken bereits manuell zugewiesen haben, suchen Sie in den Berechtigungsdateien nach diesen Tabellennamen und kommentieren Sie diese ebenfalls aus. Vergessen Sie danach nicht einen flush_privileges. Gute Beschreibung der MySQL-
Datenbank unter

Antworten:

169

Leg dich nicht mit der MySQL-Datenbank an. Dort ist viel mehr los als nur die Benutzertabelle. Ihre beste Wette ist der Befehl " SHOW GRANTS FOR". Ich habe eine Menge CLI-Wartungs-Aliase und -Funktionen in meinem .bashrc (tatsächlich meine .bash_aliases, die ich in meinem .bashrc enthalte). Diese Funktion:

mygrants()
{
  mysql -B -N $@ -e "SELECT DISTINCT CONCAT(
    'SHOW GRANTS FOR \'', user, '\'@\'', host, '\';'
    ) AS query FROM mysql.user" | \
  mysql $@ | \
  sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}'
}

Der erste mysql-Befehl generiert mit SQL gültiges SQL, das an den zweiten mysql-Befehl weitergeleitet wird. Die Ausgabe wird dann durch sed geleitet, um hübsche Kommentare hinzuzufügen.

Mit dem $ @ im Befehl können Sie Folgendes aufrufen: mygrants --host = prod-db1 --user = admin --password = secret

Sie können Ihr vollständiges Unix-Toolkit folgendermaßen verwenden:

mygrants --host=prod-db1 --user=admin --password=secret | grep rails_admin | mysql --host=staging-db1 --user=admin --password=secret

Das ist DER richtige Weg, um Benutzer zu bewegen. Ihre MySQL-ACL wird mit reinem SQL geändert.

Bruno Bronosky
quelle
Dies ist eine nette Bash-Helfer-Funktion, die großartig funktioniert. Nehmen Sie die Ausgabe davon und können Sie sie auf dem neuen Server ausführen, und die Berechtigungen werden korrekt und genau eingegeben.
Jeremy Bouse
1
Ich liebe deine Funktion, heute hat es mir viel Arbeit erspart. Danke, danke, danke ...
Fabio
2
Das ist großartig, hat aber einen großen Fehler. Ein zusätzliches "\" wird zu Unterstrichen in Datenbanknamen hinzugefügt. Wenn Sie beispielsweise einen Benutzer mit bestimmten Berechtigungen für eine Datenbank namens "foo_bar" haben, wird diese als "foo \ _bar" anstelle von "foo_bar" gerendert, sodass sie nicht korrekt importiert wird . Zumindest passiert dies, wenn Sie die Ausgabe Ihres Skripts in einer SQL-Datei speichern und dann in den neuen Server importieren. Ich habe nicht versucht, Export und Import direkt in einer Zeile zu leiten.
Matteo
1
Seien Sie vorsichtig mit diesem Befehl. Wenn Sie in der userTabelle einen Benutzer mit Host haben %, aber dann in der dbTabelle Einträge haben, bei denen hostes sich um einen expliziten Wert handelt, werden diese Einträge in der dbTabelle nicht mit dieser Methode abgerufen.
Mitar
1
@matteo Fügt -rdem 2. mysql-Befehl in der Funktion hinzu, und die doppelten Escape-Zeichen werden nicht von ausgegeben mysql. zB:mysql -r $@
lifo
45

Es gibt zwei Methoden zum Extrahieren von SQL Grants aus einer MySQL-Instanz

METHODE 1

Sie können pt-show-grants von Percona Toolkit verwenden

MYSQL_CONN="-uroot -ppassword"
pt-show-grants ${MYSQL_CONN} > MySQLUserGrants.sql

Methode # 2

Sie können pt-show-grantsmit den folgenden emulieren

MYSQL_CONN="-uroot -ppassword"
mysql ${MYSQL_CONN} --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql ${MYSQL_CONN} --skip-column-names -A | sed 's/$/;/g' > MySQLUserGrants.sql

Bei beiden Methoden wird ein reiner SQL-Speicherauszug der MySQL-Berechtigungen erstellt. Sie müssen das Skript nur noch auf einem neuen Server ausführen:

mysql -uroot -p -A < MySQLUserGrants.sql

Versuche es !!!

RolandoMySQLDBA
quelle
1
pt-show-grants ist genau das, was Sie dafür wollen, es funktioniert großartig.
Glenn Plas
Percona ist einfach großartig.
So
7
Aber Antwort 2 ist genauso gut und funktioniert ohne zusätzliche Software!
So
14

Richard Bronoskys Antwort war für mich äußerst nützlich. Danke vielmals!!!

Hier ist eine kleine Variation, die für mich nützlich war. Es ist hilfreich, um Benutzer zu übertragen, z. B. zwischen zwei Ubuntu-Installationen, auf denen phpmyadmin ausgeführt wird. Nur Dump-Berechtigungen für alle Benutzer außer root, phpmyadmin und debian-sys-maint. Der Code ist dann

mygrants()
{
mysql -B -N $@ -e "SELECT DISTINCT CONCAT(
'SHOW GRANTS FOR ''', user, '''@''', host, ''';'
) AS query FROM mysql.user WHERE user NOT IN ('root','phpmyadmin','debian-sys-maint')"  | \
mysql $@ | \
sed 's/\(GRANT .*\)/\1;/;s/^\(Grants for .*\)/## \1 ##/;/##/{x;p;x;}'
}
rmldj
quelle
2
Wenn Sie sich mein Beispiel ansehen, in dem ich grep rails_adminIhnen zeigen kann, wie Sie dies tun können, ohne für jeden Kantenfall eine spezielle Funktion zu erstellen. Verwenden Sie Greps "Invert-Match" -Option wie mygrants --host=prod-db1 --user=admin --password=secret | grep -Ev 'root|phpmyadmin|debian-sys-maint' | mysql --host=staging-db1 --user=admin --password=secret
folgt
7

Oder verwenden Sie das Percona-Toolkit (früher Maatkit) und verwenden Sie pt-show-grants(oder mk-show-grants) für diesen Zweck. Keine Notwendigkeit für umständliche Skripte und / oder gespeicherte Prozeduren.

MrkiMile
quelle
5

Sie können die 'mysql'-Datenbank mysqldumpen und in die neue importieren. Ein flush_privileges oder Neustart ist erforderlich, und Sie möchten auf jeden Fall zuerst die vorhandene mysq-Datenbank sichern.

Um zu vermeiden, dass Ihre vorhandenen Berechtigungen entfernt werden, müssen Sie die Zeilen in den Berechtigungstabellen (db, columns_priv, host, func usw.) anhängen und nicht ersetzen.

nedm
quelle
Danke @nedm. Scheint, als würde der nervige cPanel-Server, den ich versuche, um die DBS auszuschalten, die DBS 'mysql' nicht anzeigen. Ansonsten würde ich deine Antwort testen und bestätigen. Sobald ich das herausgefunden habe, werde ich zurückschauen. Vielen Dank.
Gareth
Das ist bedauerlich, aber verständlich. Wahrscheinlich wird Ihnen der Zugriff auf eine andere Datenbank als die direkt Ihrem Benutzer gehörenden auf einer gemeinsam genutzten Datenbank verwehrt.
Dave Cheney
Aua, ja, ohne Zugriff auf 'mysql' wird es schwierig sein, irgendetwas zu tun, was mit Benutzern oder Berechtigungen zu tun hat. Haben Sie Befehlszeilenzugriff? Können Sie mysqldump über das Terminal oder die Befehlszeile ausführen (NICHT über die mysql-Shell)? mysqldump -u Benutzername -ppassword mysql> mysqldump.sql
nedm
Auf die Datenbank 'mysql' konnte über das Cpanel WHM zugegriffen werden, wenn ich mich als 'root' angemeldet habe. Von dort aus kann ich auf eine Version von phpmyadmin zugreifen, die über die 'mysql'-Datenbank mit Berechtigungen verfügt
Gareth,
Das Zusammenführen in ein vorhandenes MySQL-Schema und das Extrahieren von Daten aus einem MySQL-Schema über MySQL-Dump ist mit ziemlicher Sicherheit problematisch. Sie bearbeiten ein komplexes Schema mit erzwungenen Beziehungen usw. Dieses Schema ist in der Tat so komplex, dass es eine dedizierte SQL-Syntax (GRANT, REVOKE, DROP USER usw.) für die Bearbeitung erstellt hat. Ihr Extrakt besteht jedoch nur aus INSERT-Anweisungen. Mir gehen hier die Charaktere aus. Muss ich weitermachen?
Bruno Bronosky
4

Sie können es auch als gespeicherte Prozedur ausführen:

CREATE PROCEDURE spShowGrants()
    READS SQL DATA
    COMMENT 'Show GRANT statements for users'
BEGIN
    DECLARE v VARCHAR(64) CHARACTER SET utf8;
    DECLARE c CURSOR FOR
    SELECT DISTINCT CONCAT(
        'SHOW GRANTS FOR ', user, '@', host, ';'
    ) AS query FROM mysql.user;
    DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;  
    OPEN c;
    WHILE TRUE DO
        FETCH c INTO v;
        SET @v = v;
        PREPARE stmt FROM @v;
        EXECUTE stmt;
    END WHILE;
    CLOSE c;
END

und nenne es mit

$ mysql -p -e "CALL spShowGrants" mysql

Leiten Sie dann die Ausgabe über den Befehl Richards sed, um eine Sicherung der Berechtigungen zu erhalten.

Lenny
quelle
3

Obwohl die Antwort von @Richard Bronosky richtig zu sein scheint, stieß ich auf diese Frage, nachdem ich versucht hatte, eine Reihe von Datenbanken von einem Server auf einen anderen zu migrieren, und die Lösung war viel einfacher:

server1$ mysqldump -u root -p --all-databases > dbdump.sql

server2$ mysql -u root -p < dbdump.sql

Zu diesem Zeitpunkt waren alle meine Daten sichtbar, wenn ich mich als angemeldet habe root, die mysql.userTabelle alles enthielt, was ich erwartet hatte, aber ich konnte mich nicht als einer der anderen Benutzer anmelden und fand diese Frage, vorausgesetzt, ich müsste sie erneut eingeben. erteilt die GRANTAnweisungen.

Es stellte sich jedoch heraus, dass der MySQL-Server lediglich neu gestartet werden musste, damit die aktualisierten Berechtigungen in den mysql.*Tabellen wirksam wurden:

server2$ sudo restart mysql

Hoffentlich hilft das jemand anderem dabei, eine einfache Aufgabe zu erfüllen!

Tom
quelle
Oh, und meine Situation war etwas anders als die der OPs, da ich nicht versuchte, einen Dump mit vorhandenen Datenbanken / Benutzern auf einem Server zusammenzuführen.
Tom
2
Sie müssen MySQLd nicht neu starten, um die Berechtigungen zu aktualisieren. Dies kann mit dem MySQL-Befehl 'flush privileges' erfolgen.
CloudWeavers
Das Problem bei diesem Ansatz ist, dass es nur funktioniert, wenn Quell- und Ziel-MySQL-Version identisch sind. Andernfalls kann es zu Problemen kommen, da die mysql.user-Quelltabelle andere Spalten als die mysql.user-Zieltabelle enthält.
Mitar
3

Wie wäre es mit einem PHP-Skript? :)

Zeigen Sie den Quellcode für dieses Skript an und Sie haben alle Berechtigungen aufgelistet:

//connect
mysql_select_db("mysql", mysql_connect("localhost","root",""));

//create grants select statements
$rs = mysql_query("SELECT DISTINCT CONCAT('SHOW GRANTS FOR ''', user, '''@''', host, ''';') AS query FROM user");

//iterate through grants
while ($row=mysql_fetch_array($rs)) {
    //run grant query
    $rs2 = mysql_query($row['query']);
    //iterate through results
    while($row2 = mysql_fetch_array($rs2)){
        //print results
        echo $row2[0] . ";\n\n";
    }
}
Ibrahim Lawal
quelle
2

Erstellen Sie eine Shell-Skriptdatei mit dem folgenden Code:

##############################################3
echo "SELECT DISTINCT CONCAT (\"show grants for '\", user, \"'@'\", host, \"';\") AS query FROM mysql.user; " >   script.sql    
echo "*** You will be asked to enter the root password twice ******"    
mysql -u root -p  < script.sql > output.sql ;    
cat output.sql | grep show > output1.sql  ; rm output.sql -f ; 
mysql -u root -p  < output1.sql > output.sql ;
clear
echo "-----Exported Grants-----"    
cat  output.sql ; rm  output.sql   output1.sql -f    
echo "-------------------------"
rm  script.sql -f
#

**** Führen Sie es dann auf der Shell folgendermaßen aus: Sie werden aufgefordert, das root-Passwort zweimal einzugeben, und dann wird GRANTS SQL auf dem Bildschirm angezeigt. ****


quelle
0

Einzeiler macht so ziemlich dasselbe wie der Awesome pt-show-grants:

mysql --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql --skip-column-names -A | sed 's/$/;/g'

Nur auf Basis von Unix-Tools, keine zusätzliche Software erforderlich.

Ausführen aus einer Bash-Shell, vorausgesetzt, Sie haben eine Funktion, .my.cnfmit der das Kennwort Ihres mysql rootBenutzers gelesen werden kann.

sjas
quelle
Ich habe die Hälfte von @rolandomysqldbas Post dupliziert, nachdem ich ein halbes Jahr später zurückgekommen war.
Sjas