如何从MySQL导出特权,然后导入到新服务器?


88

我知道如何使用mysqldump导出/导入数据库,这很好,但是如何将特权获取到新服务器中。

值得一提的是,新数据库上已经有几个现有数据库,我该如何导入旧服务器特权而又不破坏已有的几个数据库。

旧服务器:5.0.67-社区

新服务器:5.0.51a-24 + lenny1

编辑:我已经从旧服务器上获取了数据库“ mysql”的转储,现在想知道与新服务器上的“ mysql”数据库合并的正确方法。

我使用phpMyAdmin尝试了直接的“导入”,最后出现了关于重复项的错误(我已经手动迁移了一个)。

有没有人很好地合并两个“ mysql”数据库?


1.是否需要使用PHPMyAdmin?如果是这样,我会为您编写一些PHPMyAdmin特定说明。2.如果尝试“从mysql.user限制1选择*,请从PHPMyAdmin”;你得到结果还是错误。
布鲁诺·布罗诺斯基

1
正如我在下面提到的,我认为Richard的mygrants脚本是获取资助信息的好方法。但是,您也可以尝试编辑转储文件,以便为已经存在的用户在用户表中注释掉INSERT。从旧服务器还原的数据库的特权随后将被复制。如果您已经为还原到新框的某些数据库手动分配了特权,请在特权文件中查找这些表名,并将它们注释掉。之后别忘了flush_privileges。mysql db的完整说明,位于:grahamwideman.com/gw/tech/mysql/perms/index.htm
nedm

Answers:


169

不要搞乱mysql db。除了users表外,还有更多的事情要做。最好的选择是“ SHOW GRANTS FOR”命令。我的.bashrc(实际上是我的.bashrc中的.bash_aliases)中有很多CLI维护别名和功能。该功能:

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

这是移动用户的正确方法。您的MySQL ACL已使用纯SQL进行了修改。


这实际上是一个不错的bash辅助函数,效果很好。从中获取输出并能够在新服务器上运行,特权将被正确而准确地输入。
杰里米·布斯

1
我喜欢您的功能,今天它为我节省了很多工作。谢谢,谢谢,谢谢...
Fabio

2
这很好,但有一个大缺陷。在数据库名称中的下划线处会添加一个额外的“ \”,因此,例如,如果您在名为foo_bar的数据库上具有特定特权的用户,它将被呈现为foo \ _bar而不是foo_bar,因此将无法正确导入。至少,如果将脚本的输出保存到SQL文件中,然后将其导入到新服务器中,则会发生这种情况。我没有尝试在单一行中直接进行进出口管道。
matteo

1
使用此命令时要小心。如果user表中有一个具有host的用户%,但是db表中具有的条目host是其中的一个显式值,db则使用此方法不会检索表中的那些条目。
Mitar 2015年

1
@matteo -r在函数中添加到第二个mysql命令,并且不会输出两次转义mysql。例如:mysql -r $@
lifo

45

有两种从MySQL实例中提取SQL授权的方法

方法1

您可以使用Percona工具包中的pt-show-grants

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

两种方法都将产生MySQL授权的纯SQL转储。剩下要做的就是在新服务器上执行脚本:

mysql -uroot -p -A < MySQLUserGrants.sql

试试看 !!!


1
pt-show-grants正是您想要的,它很棒。
Glenn Plas 2014年

Percona只是纯粹的令人敬畏。
sjas 2015年

7
但是答案2同样好,不需要其他软件就可以工作!
sjas 2015年

14

理查德·布罗诺斯基(Richard Bronosky)的回答对我非常有用。非常感谢!!!

这是一个对我有用的小变化。这对于在两个运行phpmyadmin的Ubuntu安装之间转移用户很有帮助。只需为除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;}'
}

2
如果查看我的示例,则grep rails_admin可以推断出如何执行此操作,而无需为每种边缘情况创建特殊功能。像这样使用grep的“反向匹配”选项: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)。无需繁琐的脚本和/或存储过程。


5

您可以mysqldump'mysql'数据库并导入到新数据库;将需要flush_privileges或重新启动,并且您肯定要首先备份现有的mysq数据库。

为避免删除现有特权,请确保在特权表(db,columns_priv,host,func等)中添加而不是替换行。


谢谢@nedm。似乎烦人的cPanel服务器,我正在尝试关闭dbs,但未显示db'mysql'。否则,我会测试并确认您的答案。一旦弄清楚了,我会再检查一次。谢谢。
加雷斯

不幸的是,这是可以理解的,可能会阻止您访问任何数据库,但不能访问用户在共享数据库上直接拥有的数据库。
戴夫·切尼

是的,如果不能访问“ mysql”,将很难执行与用户或权限相关的任何操作。您有命令行访问权限吗?可以从终端或命令行运行mysqldump吗(不能从mysql shell运行)?mysqldump -u用户名-ppassword mysql> mysqldump.sql
nedm

如果我以“ root”身份登录,则可以从Cpanel WHM访问db“ mysql”。从那里,我可以访问phpmyadmin版本,该版本具有包含权限的“ mysql”数据库
Gareth,2009年

合并到现有的mysql模式中,通过mysqldump从mysql模式中提取的数据几乎可以确定是有问题的。您正在处理具有强制关系等的复杂模式。实际上,这种模式是如此复杂,以至于他们创建了专用的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命令通过管道输出以获取特权的备份。


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

希望这可以帮助其他人完成应该是一个简单的任务!


哦,我的情况与OP的情况略有不同,因为我没有尝试将转储合并到具有现有数据库/用户的服务器中。
汤姆(Tom)

2
您实际上不必重新启动MySQLd即可“更新特权”。可以使用MySQL命令“ flush privileges;”来完成。
CloudWeavers'5

这种方法的问题在于它仅在源MySQL版本和目标MySQL版本相同时才有效。否则,您可能会遇到问题,因为例如源mysql.user表的列与目标mysql.user表的列不同。
Mitar 2015年

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

使用以下代码创建一个shell脚本文件:

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

****然后在shell上这样运行它:将要求您输入两次根密码,然后在屏幕上显示GRANTS SQL。


0

一线表现与出色表现大致相同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 shell中执行,假设您已经可以读取用户.my.cnf密码了mysql root


半年后回来后,我复制了@rolandomysqldba的帖子的一半,我才意识到。
sjas 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.