Como posso exportar os privilégios do MySQL e depois importar para um novo servidor?

88

Eu sei como exportar / importar os bancos de dados usando o mysqldump e isso é bom, mas como faço para obter os privilégios no novo servidor.

Para obter pontos extras, já existem alguns bancos de dados existentes no novo, como importo os privilégios de servidores antigos sem diminuir o número de pares existentes.

Servidor antigo: 5.0.67-community

Novo servidor: 5.0.51a-24 + lenny1

EDIT: Eu tenho um despejo do db 'mysql' do servidor antigo e agora quero saber a maneira correta de mesclar com o db 'mysql' no novo servidor.

Tentei um 'Import' direto usando o phpMyAdmin e acabei com um erro em relação a uma duplicata (que já migrei manualmente).

Alguém tem uma maneira elegante de mesclar os dois bancos de dados 'mysql'?

Gareth
fonte
1. É um requisito para você usar o PHPMyAdmin? Se for, escreverei algumas instruções específicas do PHPMyAdmin para você. 2. No PHPMyAdmin, se você tentar "selecionar * no mysql.user limit 1;" você obtém resultados ou erro.
de Bruno Bronosky
1
Como mencionei abaixo, acho que o script de Richard sobre os migrantes é uma boa maneira de obter informações sobre subsídios. No entanto, você também pode tentar editar o arquivo de despejo para comentar INSERTs na tabela de usuários para usuários que já existem. Privilégios para os dbs restaurados do servidor antigo serão copiados. Se você já atribuiu privilégios manualmente a alguns dos dbs restaurados na nova caixa, procure esses nomes de tabela nos arquivos de privilégios e comente-os também. Não se esqueça de um flush_privileges depois. Boa descrição do banco de dados mysql em: grahamwideman.com/gw/tech/mysql/perms/index.htm
NEDM

Respostas:

169

Não mexa com o banco de dados mysql. Há muito mais acontecendo lá do que apenas a tabela de usuários. Sua melhor aposta é o comando " SHOW GRANTS FOR". Eu tenho muitos aliases e funções de manutenção da CLI no meu .bashrc (na verdade, meus .bash_aliases que eu forneço no meu .bashrc). Esta função:

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

O primeiro comando do mysql usa SQL para gerar SQL válido, que é canalizado para o segundo comando do mysql. A saída é então canalizada através do sed para adicionar comentários bonitos.

O $ @ no comando permitirá que você o chame como: mygrants --host = prod-db1 --user = admin --password = secret

Você pode usar seu kit de ferramentas unix completo da seguinte maneira:

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

Essa é a maneira certa de mover usuários. Sua MySQL ACL é modificada com SQL puro.

Bruno Bronosky
fonte
Esta é realmente uma boa função de auxiliar do bash que funciona muito bem. Pegue a saída disso e seja capaz de executar no novo servidor e os privilégios serão inseridos de maneira correta e precisa.
Jeremy Bouse
1
Adoro a sua função, hoje me poupou muito trabalho. Obrigado, obrigado, obrigado ...
Fabio
2
Isso é ótimo, mas tem uma grande falha. Um "\" extra é adicionado aos sublinhados nos nomes dos bancos de dados; portanto, se você tiver, por exemplo, um usuário com privilégios específicos em um banco de dados chamado foo_bar, ele será renderizado como foo \ _bar em vez de foo_bar, para que não seja importado corretamente. . Pelo menos, isso acontece se você salvar a saída do script em um arquivo SQL e depois importá-la para o novo servidor. Eu não tentei a tubulação direta de exportação e importação em uma única linha.
Matteo
1
Tenha cuidado com este comando. Se você tiver na usertabela um usuário com host %, mas na dbtabela hosthouver entradas em que há um valor explícito, essas entradas na dbtabela não serão recuperadas usando esse método.
Mitar
1
@matteo Adicione -rao segundo comando mysql na função e os escapes duplos não serão exibidos mysql. por exemplo:mysql -r $@
lifo 12/09/16
45

Existem dois métodos para extrair o SQL Grants de uma instância do MySQL

MÉTODO 1

Você pode usar pt-show- grant do Percona Toolkit

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

MÉTODO # 2

Você pode emular pt-show-grantscom o seguinte

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

Qualquer um dos métodos produzirá um despejo SQL puro das concessões do MySQL. Tudo o que resta a fazer é executar o script em um novo servidor:

mysql -uroot -p -A < MySQLUserGrants.sql

De uma chance !!!

RolandoMySQLDBA
fonte
1
pt-show-grant é exatamente o que você deseja para isso, funciona muito bem.
amigos estão dizendo sobre glenn
Percona é apenas pura grandiosidade.
sjas
7
Mas a resposta 2 é tão boa e funcionará sem software adicional!
sjas
14

A resposta de Richard Bronosky foi extremamente útil para mim. Muito Obrigado!!!

Aqui está uma pequena variação que foi útil para mim. É útil para transferir usuários, por exemplo, entre duas instalações do Ubuntu executando o phpmyadmin. Apenas despeje privilégios para todos os usuários, exceto root, phpmyadmin e debian-sys-maint. O código é então

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
fonte
2
Se você olhar para o meu exemplo, onde grep rails_adminvocê pode inferir como fazer isso sem criar uma função especial para cada caso extremo. Use a opção "partida invertida" do grep da seguinte maneira: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 8/17/17
7

Ou utilize o percona-toolkit (antigo maatkit) e use pt-show-grants(ou mk-show-grants) para esse fim. Não há necessidade de scripts pesados ​​e / ou procedimentos armazenados.

MrkiMile
fonte
5

Você pode mysqldump o banco de dados 'mysql' e importar para o novo; será necessário um flush_privileges ou restart e você definitivamente desejará fazer o backup do banco de dados mysq existente primeiro.

Para evitar remover os privilégios existentes, anexe em vez de substituir linhas nas tabelas de privilégios (db, column_priv, host, func, etc.).

nedm
fonte
Obrigado @nedm. Parece que o irritante servidor cPanel que estou tentando desativar o dbs não mostra o db 'mysql'. Caso contrário, eu testaria e afirmaria sua resposta. Depois que eu descobrir isso, volto. Obrigado.
1630 Gareth
Isso é lamentável, mas compreensível, você provavelmente está impedido de acessar qualquer banco de dados, exceto os de propriedade direta do usuário em um banco de dados compartilhado.
Dave Cheney
Ai, sim, sem acesso ao 'mysql', será difícil fazer algo relacionado a usuários ou permissões. Você tem acesso à linha de comando? Você pode executar o mysqldump no terminal ou na linha de comando (NÃO no shell do mysql)? mysqldump -u nome de usuário -ppassword mysql> mysqldump.sql
nedm
O banco de dados 'mysql' estava acessível no Cpanel WHM se eu fiz login como 'root'. A partir daí eu posso acessar uma versão do phpmyadmin que tem que contêm as permissões de banco de dados dos mysql '
Gareth
Mesclando em um esquema mysql existente, os dados extraídos de um esquema mysql via mysqldump são quase certamente problemáticos. Você está manipulando um esquema complexo com relacionamentos forçados, etc. Esse esquema é tão complexo que, de fato, eles criaram sintaxe SQL dedicada (GRANT, REVOKE, DROP USER etc.) para lidar com ele. Sua extração, no entanto, consiste apenas em instruções INSERT. Estou ficando sem personagens aqui. Preciso continuar?
11789 Bruno Bronosky
4

Você também pode fazer isso como um procedimento armazenado:

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 chame com

$ mysql -p -e "CALL spShowGrants" mysql

em seguida, canalize a saída através do comando Richards sed para obter um backup dos privilégios.

Lenny
fonte
3

Embora pareça que a resposta de Richard Bronosky seja a correta, me deparei com essa pergunta depois de tentar migrar um conjunto de bancos de dados de um servidor para outro e a solução era muito mais simples:

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

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

Nesse momento, todos os meus dados estavam visíveis se eu fizesse login como root, a mysql.usertabela tinha tudo o que eu esperava, mas não consegui fazer login como nenhum dos outros usuários e encontrei essa pergunta assumindo que eu precisaria emitir as GRANTdeclarações.

No entanto, verifica-se que o servidor mysql simplesmente precisava ser reiniciado para que os privilégios atualizados nas mysql.*tabelas entrassem em vigor:

server2$ sudo restart mysql

Espero que ajude alguém a alcançar o que deveria ser uma tarefa simples!

Tom
fonte
Ah, e minha situação era um pouco diferente da do OP, pois eu não estava tentando mesclar um despejo em um servidor com bancos de dados / usuários existentes.
Tom
2
Você não precisa realmente reiniciar o MySQLd para 'atualizar os privilégios'. Isso pode ser feito com o comando MySQL 'flush privilégios;'
CloudWeavers
O problema dessa abordagem é que ela funciona apenas quando a versão MySQL de origem e destino é a mesma. Caso contrário, você poderá ter problemas porque a tabela mysql.user de origem possui colunas diferentes da tabela mysql.user de destino, por exemplo.
Mitar 26/06
3

Que tal um script PHP? :)

Veja a fonte neste script e você terá todos os privilégios listados:

//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
fonte
2

crie um arquivo de script de shell com o seguinte código:

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

****, em seguida, execute-o no shell assim: você será solicitado a digitar a senha root duas vezes e, em seguida, o GRANTS SQL será exibido na tela. ****


fonte
0

One-liner fazendo praticamente o mesmo que o incrível 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'

Baseado apenas em ferramentas unix, não é necessário software adicional.

Execute de dentro de um shell bash, supondo que você tenha um trabalho em .my.cnfque a senha do seu mysql rootusuário possa ser lida.

sjas
fonte
dupliquei metade do post de @rolandomysqldba depois de voltar meio ano depois, acabei de perceber.
Sj # 13/16