Come posso esportare i privilegi da MySQL e quindi importarli in un nuovo server?


88

So come esportare / importare i database usando mysqldump e va bene, ma come posso ottenere i privilegi nel nuovo server.

Per i punti extra, ci sono già un paio di database esistenti su quello nuovo, come posso importare i privilegi dei vecchi server senza nuocere alla coppia esistente di quelli.

Vecchio server: 5.0.67-community

Nuovo server: 5.0.51a-24 + lenny1

EDIT: Ho un dump del db 'mysql' dal vecchio server e ora voglio conoscere il modo corretto di unire il 'mysql' db sul nuovo server.

Ho provato un 'Import' semplice usando phpMyAdmin e ho finito con un errore riguardante un duplicato (uno che ho già migrato manualmente).

Qualcuno ha un modo elegante di unire i due database "mysql"?


1. È necessario utilizzare PHPMyAdmin? In tal caso scriverò alcune istruzioni specifiche per PHPMyAdmin. 2. Da PHPMyAdmin se si tenta di "selezionare * da mysql.user limit 1;" ottieni risultati o un errore.
Bruno Bronosky,

1
Come ho detto di seguito, penso che la sceneggiatura di Richard Mygrants sia un buon modo per ottenere informazioni sulle sovvenzioni. Tuttavia, puoi anche provare a modificare il file di dump per commentare INSERT nella tabella utente per gli utenti che già esistono. Verranno quindi copiati i privilegi per i dbs ripristinati dal vecchio server. Se hai già assegnato i privilegi manualmente per alcuni dei dbs ripristinati nella nuova casella, cerca questi nomi di tabella nei file dei privilegi e commentali anche questi. Non dimenticare successivamente un flush_privileges. Buona descrizione del db mysql su: grahamwideman.com/gw/tech/mysql/perms/index.htm
nedm

Risposte:


169

Non scherzare con il mysql db. C'è molto altro da fare lì oltre alla semplice tabella degli utenti. La tua scommessa migliore è il comando " MOSTRA SOVVENZIONI PER". Ho molti alias di manutenzione della CLI e funzioni nel mio .bashrc (in realtà i miei .bash_alias che ho sorgente nel mio .bashrc). Questa funzione:

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;}'
}

Il primo comando mysql utilizza SQL per generare un SQL valido che viene reindirizzato al secondo comando mysql. L'output viene quindi reindirizzato attraverso sed per aggiungere commenti piuttosto.

$ @ Nel comando ti permetterà di chiamarlo come: mygrants --host = prod-db1 --user = admin --password = secret

È possibile utilizzare il kit di strumenti unix completo su questo in questo modo:

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

Questo è il modo giusto per spostare gli utenti. Il tuo ACL MySQL è modificato con SQL puro.


Questa è in realtà una bella funzione di supporto bash che funziona alla grande. Prendi l'output da questo ed essere in grado di funzionare sul nuovo server e i privilegi verrebbero inseriti in modo corretto e accurato.
Jeremy Bouse,

1
Adoro la tua funzione, oggi mi ha risparmiato molto lavoro. Grazie, grazie, grazie ...
Fabio,

2
Questo è fantastico ma ha un grosso difetto. Un "\" aggiuntivo viene aggiunto ai caratteri di sottolineatura nei nomi dei database, quindi se si dispone ad esempio di un utente con privilegi specifici su un database chiamato foo_bar, verrà visualizzato come foo \ _bar anziché foo_bar, quindi non verrà importato correttamente . Almeno, questo accade se si salva l'output dallo script in un file SQL e lo si importa nel nuovo server. Non ho provato il piping diretto di esportazione e importazione in una sola riga.
matteo,

1
Stai attento con questo comando. Se nella usertabella è presente un utente con host %, ma nella dbtabella sono presenti voci in cui hostè presente un valore esplicito, tali voci nella dbtabella non vengono recuperate utilizzando questo metodo.
Mitar,

1
@matteo Aggiungi -ral secondo comando mysql nella funzione e le doppie escape non verranno emesse da mysql. ad es .:mysql -r $@
lifo,

45

Esistono due metodi per l'estrazione di SQL Grants da un'istanza MySQL

METODO # 1

Puoi usare pt-show-grants da Percona Toolkit

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

METODO # 2

Puoi emulare pt-show-grantscon quanto segue

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

Entrambi i metodi produrranno un dump SQL puro delle sovvenzioni MySQL. Non resta che eseguire lo script su un nuovo server:

mysql -uroot -p -A < MySQLUserGrants.sql

Provaci !!!


1
pt-show-grants è esattamente quello che vuoi per questo, funziona benissimo.
Glenn Plas,

Percona è semplicemente pura bellezza.
sjas,

7
Ma la risposta n. 2 è altrettanto valida e funzionerà senza software aggiuntivo!
sjas,

14

La risposta di Richard Bronosky è stata estremamente utile per me. Grazie molto!!!

Ecco una piccola variazione che mi è stata utile. È utile per trasferire utenti, ad esempio tra due installazioni di Ubuntu che eseguono phpmyadmin. Scarica i privilegi per tutti gli utenti tranne root, phpmyadmin e debian-sys-maint. Il codice è quindi

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;}'
}

2
Se guardi il mio esempio in cui grep rails_adminposso dedurre come farlo senza fare una funzione speciale per ogni caso limite. Usa l'opzione "inverti partita" di grep in questo modo:mygrants --host=prod-db1 --user=admin --password=secret | grep -Ev 'root|phpmyadmin|debian-sys-maint' | mysql --host=staging-db1 --user=admin --password=secret
Bruno Bronosky,

7

Oppure utilizza percona-toolkit (ex maatkit) e usa pt-show-grants(o mk-show-grants) a tale scopo. Non sono necessari script ingombranti e / o procedure memorizzate.


5

Puoi mysqldump il database 'mysql' e importarlo in quello nuovo; saranno richiesti flush_privileges o restart e sicuramente vorrai prima eseguire il backup del database mysq esistente.

Per evitare di rimuovere i privilegi esistenti, assicurarsi di aggiungere anziché sostituire le righe nelle tabelle dei privilegi (db, column_priv, host, func, ecc.).


Grazie @nedm. Sembra che il fastidioso server cPanel che sto provando a togliere il dbs non mostri il db 'mysql'. Altrimenti testerei e affermerei la tua risposta. Una volta che lo capirò tornerò indietro. Grazie.
Gareth,

Ciò è sfortunato ma comprensibile, probabilmente ti viene impedito di accedere a qualsiasi database tranne quelli direttamente posseduti dal tuo utente su un db condiviso.
Dave Cheney,

Ahi, sì, senza l'accesso a "mysql" sarà difficile fare qualsiasi cosa relativa agli utenti o alle autorizzazioni. Hai accesso alla riga di comando? Puoi eseguire mysqldump dal terminale o dalla riga di comando (NON dalla shell mysql)? mysqldump -u username -ppassword mysql> mysqldump.sql
nedm

Il db "mysql" era accessibile da Cpanel WHM se eseguivo l'accesso come "root". Da lì posso accedere a una versione di phpmyadmin che ha il database 'mysql' contenente permessi
Gareth,

Fondendosi in uno schema mysql esistente, i dati estratti da uno schema mysql tramite mysqldump sono quasi sicuramente problematici. Stai manipolando uno schema complesso con relazioni forzate, ecc. Questo schema è così complesso, infatti, che hanno creato una sintassi SQL dedicata (GRANT, REVOKE, DROP USER, ecc.) Per gestirla. Il tuo estratto, tuttavia, consiste solo di istruzioni INSERT. Sto finendo i personaggi qui. Devo continuare?
Bruno Bronosky,

4

Potresti anche farlo come una procedura memorizzata:

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

e chiamalo con

$ mysql -p -e "CALL spShowGrants" mysql

quindi reindirizzare l'output tramite il comando sed di Richard per ottenere un backup dei privilegi.


3

Mentre sembra che la risposta di @Richard Bronosky sia quella corretta, mi sono imbattuto in questa domanda dopo aver provato a migrare un set di database da un server a un altro e la soluzione era molto più semplice:

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

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

A questo punto, tutti i miei dati erano visibili se eseguissi l'accesso come root, la mysql.usertabella conteneva tutto quello che mi aspettavo, ma non potevo accedere come nessuno degli altri utenti e ho trovato questa domanda supponendo che avrei dovuto ri rilasciare le GRANTdichiarazioni.

Tuttavia, risulta che il server mysql doveva semplicemente essere riavviato per rendere effettivi i privilegi aggiornati nelle mysql.*tabelle:

server2$ sudo restart mysql

Spero che ciò aiuti qualcun altro a raggiungere quello che dovrebbe essere un compito semplice!


Oh, e la mia situazione era leggermente diversa da quella degli OP, in quanto non stavo cercando di unire un dump in un server con database / utenti esistenti.
Tom,

2
In realtà non è necessario riavviare MySQLd per "aggiornare i privilegi". Può essere fatto con il comando MySQL 'flush privileges;'
CloudWeavers,

Il problema con questo approccio è che funziona solo quando sia la versione MySQL di origine che quella di destinazione sono uguali. Altrimenti potresti avere problemi perché la tabella mysql.user di origine ha colonne diverse rispetto alla tabella mysql.user di destinazione, ad esempio.
Mitar,

3

Che ne dici di uno script PHP? :)

Visualizza la fonte su questo script e avrai tutti i privilegi elencati:

//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";
    }
}

2

creare un file di script shell con il seguente codice:

############################################## 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
#

**** quindi eseguilo sulla shell in questo modo: ti verrà chiesto di inserire la password di root due volte e quindi GRANTS SQL verrà visualizzato sullo schermo. ****


0

One-liner fa praticamente lo stesso del fantastico 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'

Basato solo su strumenti unix, non è necessario alcun software aggiuntivo.

Eseguire all'interno di una shell bash, si presume che tu abbia un funzionamento in .my.cnfcui è mysql rootpossibile leggere la password dell'utente.


ho duplicato la metà del post di @rolandomysqldba dopo essere tornato sei mesi dopo, mi sono appena reso conto.
sjas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.