Как я могу экспортировать привилегии из MySQL, а затем импортировать на новый сервер?

88

Я знаю, как экспортировать / импортировать базы данных, используя mysqldump, и это нормально, но как мне получить права на новый сервер.

Что касается дополнительных баллов, на новой уже есть пара существующих баз данных, как мне импортировать привилегии старых серверов, не удаляя пару существующих.

Старый сервер: сообщество 5.0.67

Новый сервер: 5.0.51a-24 + lenny1

РЕДАКТИРОВАТЬ: я получил дамп базы данных «mysql» со ​​старого сервера и теперь хочу знать, как правильно объединить с базой данных «mysql» на новом сервере.

Я попытался выполнить прямой импорт с помощью phpMyAdmin, и в результате возникла ошибка, связанная с дубликатом (который я уже перенес вручную).

У кого-нибудь есть элегантный способ объединения двух баз данных «mysql»?

Gareth
источник
1. Требуется ли вам использовать PHPMyAdmin? Если это так, я напишу некоторые конкретные инструкции PHPMyAdmin для вас. 2. В PHPMyAdmin, если вы попытаетесь «выбрать * из mysql.user limit 1;» Вы получаете результаты или ошибку.
Бруно Броноски
1
Как я упоминал ниже, я думаю, что сценарий Ричарда mygrants - это хороший способ получить информацию о гранте. Однако вы также можете попробовать отредактировать файл дампа, чтобы закомментировать INSERT в пользовательской таблице для пользователей, которые уже существуют. Привилегии для БД, восстановленных со старого сервера, будут скопированы. Если вы уже назначили привилегии вручную для некоторых из БД, которые вы восстановили в новом окне, найдите эти имена таблиц в файлах привилегий и закомментируйте их тоже. Не забудьте потом flush_privileges. Хорошее описание базы
данных

Ответы:

169

Не связывайтесь с mysql db. Там происходит намного больше, чем просто таблица пользователей. Ваша лучшая ставка - это команда « ПОКАЗАТЬ ГРАНТЫ ДЛЯ». У меня есть много псевдонимов и функций обслуживания CLI в моем .bashrc (на самом деле мой .bash_aliases, который я использую в своем .bashrc). Эта функция:

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

Первая команда mysql использует SQL для генерации действительного SQL, который передается второй команде mysql. Выходные данные затем передаются через sed, чтобы добавить красивые комментарии.

$ @ В команде позволит вам назвать его так: mygrants --host = prod-db1 --user = admin --password = secret

Вы можете использовать свой полный набор инструментов Unix для этого следующим образом:

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

Это правильный способ перемещения пользователей. Ваш ACL MySQL модифицируется чистым SQL.

Бруно Броноски
источник
На самом деле это хорошая вспомогательная функция bash, которая прекрасно работает. Возьмите вывод с этого и сможете работать на новом сервере, и привилегии будут введены правильно и точно.
Джереми Бауз
1
Мне нравится твоя функция, сегодня она спасла мне много работы. Спасибо, спасибо, спасибо ...
Фабио
2
Это здорово, но у него есть один большой недостаток. В именах баз данных добавляется дополнительный символ «\», поэтому если у вас есть, например, пользователь с определенными правами доступа к базе данных с именем foo_bar, он будет отображаться как foo \ _bar вместо foo_bar, поэтому он не будет импортирован правильно , По крайней мере, это происходит, если вы сохраняете вывод скрипта в файл SQL, а затем импортируете его на новый сервер. Я не пробовал прямой экспорт и импорт в одну строку.
Маттео
1
Будьте осторожны с этой командой. Если у вас в userтаблице есть пользователь с хостом %, но в dbтаблице у вас есть записи, где hostесть явное значение, эти записи в dbтаблице не будут получены с использованием этого метода.
Митар
1
@matteo Добавьте -rк 2-й команде mysql в функции, и двойные экранированные символы не будут выведены mysql. Например:mysql -r $@
Lifo
45

Существует два метода извлечения грантов SQL из экземпляра MySQL.

МЕТОД №1

Вы можете использовать pt-show-grants из Percona Toolkit

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

МЕТОД № 2

Вы можете подражать pt-show-grantsследующим

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

Любой метод будет производить чистый SQL-дамп грантов MySQL. Осталось только выполнить скрипт на новом сервере:

mysql -uroot -p -A < MySQLUserGrants.sql

Попробуйте!

RolandoMySQLDBA
источник
1
pt-show-grants - это именно то, что вам нужно для этого, оно прекрасно работает.
Гленн Плас
Percona - это просто потрясающая вещь.
Sjas
7
Но ответ №2 так же хорош и будет работать без дополнительного программного обеспечения!
Sjas
14

Ответ Ричарда Броноски был чрезвычайно полезен для меня. Большое спасибо!!!

Вот небольшой вариант, который был полезен для меня. Это полезно для переноса пользователей, например, между двумя установками Ubuntu, на которых работает phpmyadmin. Просто сохраните привилегии для всех пользователей, кроме root, phpmyadmin и debian-sys-maint. Код тогда

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
источник
2
Если вы посмотрите на мой пример, где я, grep rails_adminвы можете сделать вывод, как это сделать, не делая специальной функции для каждого крайнего случая. Используйте опцию grep "invert-match", например, так: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

Или используйте percona-toolkit (бывший maatkit) и используйте pt-show-grants(или mk-show-grants) для этой цели. Нет необходимости в громоздких скриптах и ​​/ или хранимых процедурах.

MrkiMile
источник
5

Вы можете mysqldump базу данных «mysql» и импортировать в новую; потребуется flush_privileges или перезагрузка, и вы определенно захотите сначала сделать резервную копию существующей базы данных mysq.

Чтобы избежать удаления существующих привилегий, обязательно добавляйте, а не заменяйте строки в таблицах привилегий (db, columns_priv, host, func и т. Д.).

nedm
источник
Спасибо @недм. Похоже, раздражающий сервер cPanel, который я пытаюсь отключить, не показывает db 'mysql'. В противном случае я бы проверил и подтвердил ваш ответ. Как только я это выясню, я проверю обратно. Благодарю.
Гарет
Это прискорбно, но понятно, вам, вероятно, запрещен доступ к какой-либо базе данных, кроме тех, которые непосредственно принадлежат вашему пользователю в общей базе данных.
Дейв Чейни
Да, без доступа к mysql будет сложно что-либо сделать с пользователями или разрешениями. У вас есть доступ к командной строке? Можете ли вы запустить mysqldump из терминала или командной строки (НЕ из оболочки mysql)? mysqldump -u username -ppassword mysql> mysqldump.sql
недм
БД «mysql» была доступна из Cpanel WHM, если я вошел в систему как «root». Оттуда я могу получить доступ к версии phpmyadmin, в которой есть база данных «mysql», содержащая разрешения
Gareth
Слияние с существующей схемой mysql, данные, извлеченные из схемы mysql через mysqldump, почти наверняка будут проблематичными. Вы управляете сложной схемой с помощью принудительных отношений и т. Д. Эта схема настолько сложна, что фактически они создали специальный синтаксис SQL (GRANT, REVOKE, DROP USER и т. Д.) Для работы с ним. Ваша выписка, однако, состоит только из операторов INSERT. У меня кончаются персонажи здесь. Нужно ли продолжать?
Бруно Броноски
4

Вы также можете сделать это как хранимую процедуру:

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

и позвони с

$ mysql -p -e "CALL spShowGrants" mysql

затем передайте вывод через команду Richards sed, чтобы получить резервную копию привилегий.

Lenny
источник
3

Хотя, похоже, ответ @Richard Bronosky правильный, я наткнулся на этот вопрос после попытки перенести набор баз данных с одного сервера на другой, и решение оказалось намного проще:

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

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

На этом этапе все мои данные были видны, если я вошел в систему как root, в mysql.userтаблице было все, что я ожидал, но я не мог войти в систему как любой из других пользователей и нашел этот вопрос, предполагая, что мне придется повторно оформить GRANTзаявления.

Однако оказывается, что сервер mysql просто необходимо было перезапустить, чтобы обновленные привилегии в mysql.*таблицах вступили в силу:

server2$ sudo restart mysql

Надеюсь, это поможет кому-то еще достичь того, что должно быть простой задачей!

Том
источник
Да, и моя ситуация немного отличалась от ОП, в которой я не пытался объединить дамп в сервер с существующими базами данных / пользователями.
Том
2
На самом деле вам не нужно перезапускать MySQLd для «обновления прав». Это можно сделать с помощью команды MySQL «очистить привилегии»;
CloudWeavers
Проблема с этим подходом состоит в том, что он работает только тогда, когда исходная и целевая версии MySQL совпадают. В противном случае у вас могут возникнуть проблемы, потому что исходная таблица mysql.user имеет столбцы, отличные от целевой таблицы mysql.user, например.
Митар
3

Как насчет PHP-скрипта? :)

Просмотрите исходный код этого скрипта, и вы получите все перечисленные привилегии:

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

создайте файл сценария оболочки со следующим кодом:

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

**** затем запустите его на оболочке следующим образом: вам будет предложено дважды ввести пароль root, а затем на экране отобразится GRANTS SQL. ****


источник
0

One-liner делает почти то же самое, что и 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'

На основе только инструментов Unix, дополнительное программное обеспечение не требуется.

Выполните из оболочки bash, предполагается, что у вас есть работа, .my.cnfгде mysql rootможно прочитать пароль вашего пользователя.

sjas
источник
Я дублировал половину поста @rolandomysqldba после того, как вернулся через полгода, я только что понял.
sjas