How to Export & Import Existing User (with its Privileges!)
我有一个现有的MySQL实例(测试),包含2个数据库和一些用户,每个用户对每个数据库具有不同的访问权限。
我现在需要复制其中一个数据库(进入生产)和与之关联的用户。
复制数据库很简单:
出口:
进口:
1 | mysql -u root -p -h localhost secondb < secondb_schema.sql |
但是,我没有找到从命令行(mysql内部或外部)导出和导入用户的简单方法。
如何从命令行导出和导入用户?
更新:到目前为止,我已经找到了完成此操作的手动(因此容易出错)的步骤:
然后找到它的补助金:
1 2 |
然后使用上面"show grants"命令的结果中列出的授权手动创建用户。
我更喜欢更安全,更自动化的方式。 有吗?
我发现导出用户的最简单方法之一是使用Percona的工具pt-show-grants。 Percona工具套件免费,易于安装,易于使用,并提供大量文档。
这是向所有用户或特定用户显示的简单方法。它以SQL格式列出了所有授权和输出。我将举例说明如何显示test_user的所有授权:
1 | shell> pt-show-grants --only test_user |
该命令的输出示例:
1 2 |
我通常将输出重新编译成文件,以便我可以编辑我需要的内容,或者将其加载到mysql中。
或者,如果您不想使用Percona工具并且想要转储所有用户,则可以以这种方式使用mysqldump:
注意: - flush特权不适用于此,因为整个数据库未被转储。这意味着您需要手动运行它。
1 | shell> mysql -e"FLUSH PRIVILEGES" |
1 2 3 4 5 | mysql -u<user> -p<password> -h<host> -e"select concat('show grants for ','\'',user,'\'@\'',host,'\'') from mysql.user"> user_list_with_header.txt sed '1d' user_list_with_header.txt > ./user.txt while read user; do mysql -u<user> -p<password> -h<host> -e"$user"> user_grant.txt; sed '1d' user_grant.txt >> user_privileges.txt; echo"flush privileges">> user_privileges.txt; done < user.txt awk '{print $0";"}' user_privileges.txt >user_privileges_final.sql rm user.txt user_list_with_header.txt user_grant.txt user_privileges.txt |
上面的脚本将在linux环境中运行,输出将是user_privileges_final.sql,您可以在要复制用户权限的新mysql服务器中导入。
更新:第二个mysql语句的用户缺少
这些是我现在用作日常备份脚本的一部分(需要root shell和MySQL访问,linux shell,并使用mysql内置架构:
首先,我创建一个包含root密码的文件/var/backup/mysqlroot.cnf,这样我就可以自动化我的脚本,而不是硬编码其中的任何密码:
然后我创建一个导出脚本,它转储创建用户命令和这样的授权:
1 2 3 | touch /var/backup/backup_sql.sh chmod 700 /var/backup/backup_sql.sh vi /var/backup/backup_sql.sh |
然后写下面的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #!/bin/bash mysql --defaults-extra-file=/var/backup/mysqlroot.cnf -sNe" \ SELECT \ CONCAT( 'CREATE USER \'', User, '\'@\'', Host, '\' IDENTIFIED BY ', authentication_string, '\;' ) AS User \ FROM mysql.user \ WHERE \ User NOT LIKE 'mysql.%' AND CONCAT( User, Host ) <> 'rootlocalhost' AND User <> 'debian-sys-maint' \ " mysql --defaults-extra-file=/var/backup/mysqlroot.cnf -sNe" \ SELECT \ CONCAT( '\'', User, '\'@\'', Host, '\'' ) as User FROM mysql.user \ WHERE \ User NOT LIKE 'mysql.%' \ AND CONCAT( User, Host ) <> 'rootlocalhost' \ AND User <> 'debian-sys-maint' \ " | sort | while read u ; do echo"-- $u"; mysql --defaults-extra-file=/var/backup/mysqlroot.cnf -sNe"show grants for $u" | sed 's/$/;/' done |
然后我只需要像这样运行它:
/var/backup/backup_sql.sh> /tmp/exportusers.sql
作为@ Sergey-Podushkin的答案的补充,这个shell脚本代码适用于我:
1 |
我有同样的问题。解决方案是在导入备份后,您需要执行"刷新权限"。然后,用户的权限将在原始数据库中处于活动状态。
所以
mysql -u root -p -h localhost secondb < secondb_schema.sql
mysql -u root;
then in mysql:"flush privileges;"
PhpMyAdmin您可以使用phpMyAdmin。
登录并转到您的数据库或用户有权访问的表。
选择权限
所有有权访问的用户都在那里。
选择导出。所有GRANTS的小窗口都准备好复制和粘贴。
另一个bash one-liner for linux使用而不是Percona工具:
1 | mysql -u<user> -p<password> -h<host> -N mysql -e"select concat("'", user, "'@'", host, "'"), authentication_string from user where not user like 'mysql.%'" | while read usr pw ; do echo"GRANT USAGE ON *.* TO $usr IDENTIFIED BY PASSWORD '$pw';" ; mysql -u<user> -p<password> -h<host> -N -e"SHOW GRANTS FOR $usr" | grep -v 'GRANT USAGE' | sed 's/\(\S\)$/\1;/' ; done |
用于循环用户以获取grant命令的PHP脚本将如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | // Set up database root credentials $host = 'localhost'; $user = 'root'; $pass = 'YOUR PASSWORD'; // ---- Do not edit below this ---- // Misc settings header('Content-type: text/plain; Charset=UTF-8'); // Final import queries goes here $export = array(); // Connect to database try { $link = new PDO("mysql:host=$host;dbname=mysql", $user, $pass); } catch (PDOException $e) { printf('Connect failed: %s', $e->getMessage()); die(); } // Get users from database $statement = $link->prepare("select `user`, `host`, `password` FROM `user`"); $statement->execute(); while ($row = $statement->fetch()) { $user = $row[0]; $host = $row[1]; $pass = $row[2]; $export[] = 'CREATE USER \''. $user .'\'@\''. $host .'\' IDENTIFIED BY \''. $pass .'\''; // Fetch any permissions found in database $statement2 = $link->prepare('SHOW GRANTS FOR \''. $user .'\'@\''. $host .'\''); $statement2->execute(); if ($row2 = $statement2->fetch()) { $export[] = $row2[0]; } } $link = null; echo implode("; ", $export); |
要点:https://gist.github.com/zaiddabaeen/e88a2d10528e31cd6692
我用一个小的C#程序解决了这个问题。这里有代码生成脚本或直接从源到目标应用授权。如果从Windows - > * nix环境移植,您可能必须考虑区分大小写问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | using System; using MySql.Data.MySqlClient; using System.Configuration; using System.IO; using System.Collections.Generic; namespace GenerateUsersScript { class Program { static void Main(string[] args) { List<string> grantsQueries = new List<string>(); // Get A Show Grants query for each user using (MySqlConnection sourceConn = OpenConnection("sourceDatabase")) { using (MySqlDataReader usersReader = GetUsersReader(sourceConn)) { while (usersReader.Read()) { grantsQueries.Add(String.Format("SHOW GRANTS FOR '{0}'@'{1}'", usersReader[0], usersReader[1])); } } Console.WriteLine("Exporting Grants For {0} Users", grantsQueries.Count); using (StreamWriter writer = File.CreateText(@".\UserPermissions.Sql")) { // Then Execute each in turn foreach (string grantsSql in grantsQueries) { WritePermissionsScript(sourceConn, grantsSql, writer); } //using (MySqlConnection destConn = OpenConnection("targetDatabase")) //{ // MySqlCommand command = destConn.CreateCommand(); // foreach (string grantsSql in grantsQueries) // { // WritePermissionsDirect(sourceConn, grantsSql, command); // } //} } } Console.WriteLine("Done - Press A Key to Continue"); Console.ReadKey(); } private static void WritePermissionsDirect(MySqlConnection sourceConn, string grantsSql, MySqlCommand writeCommand) { MySqlCommand cmd = new MySqlCommand(grantsSql, sourceConn); using (MySqlDataReader grantsReader = cmd.ExecuteReader()) { while (grantsReader.Read()) { try { writeCommand.CommandText = grantsReader[0].ToString(); writeCommand.ExecuteNonQuery(); } catch (Exception ex) { Console.WriteLine(grantsReader[0].ToString()); Console.WriteLine(ex.Message); } } } } private static void WritePermissionsScript(MySqlConnection conn, string grantsSql, StreamWriter writer) { MySqlCommand command = new MySqlCommand(grantsSql, conn); using (MySqlDataReader grantsReader = command.ExecuteReader()) { while (grantsReader.Read()) { writer.WriteLine(grantsReader[0] +";"); } } writer.WriteLine(); } private static MySqlDataReader GetUsersReader(MySqlConnection conn) { string queryString = String.Format("SELECT User, Host FROM USER"); MySqlCommand command = new MySqlCommand(queryString, conn); MySqlDataReader reader = command.ExecuteReader(); return reader; } private static MySqlConnection OpenConnection(string connName) { string connectionString = ConfigurationManager.ConnectionStrings[connName].ConnectionString; MySqlConnection connection = new MySqlConnection(connectionString); connection.Open(); return connection; } } } |
使用包含...的app.config
1 2 3 4 | <connectionStrings> </connectionStrings> |