28

I am moving from one server to another and I want to backup all databases + users/privileges/passwords from my MySQL Server. I found to backup a database using mysqldump, but I cannot figure out, how to backup all users and the given privileges. Is there a way to achieve this or do I have to set this newly up on the new server?

4
  • From MySql 5.7 and onwards, mysqldump --users, can do this Commented Nov 27, 2022 at 1:13
  • @KjeldFlarup I think you meant mysqlpump --users
    – Joseph
    Commented Jun 7, 2023 at 19:10
  • Dude, that question is 8 years old...
    – Nidhoegger
    Commented Jul 2, 2023 at 11:44
  • 1
    @Nidhoegger and people still need to know how to do this, and come here from google looking for that answer. Even after 8 years.
    – John Smith
    Commented Nov 6, 2023 at 11:11

3 Answers 3

27

The 'mysql' database contains users/privileges/passwords. So take the dump of mysql database along with other databases

mysqldump [options] --all-databases > all_databases_dump.sql

mysqldump -u root -p mysql user > user_table_dump.sql

These mysql database tables contain grant information

user: User accounts, global privileges, and other non-privilege columns.

db: Database-level privileges.

tables_priv: Table-level privileges.

columns_priv: Column-level privileges.

procs_priv: Stored procedure and function privileges.

After restoring cross check with

select Host, user, password from user ;

SHOW GRANTS FOR 'user'@'localhost';
2
  • 11
    Caution. If you will be loading this into a newer version of MySQL, the dump of mysql.user may fail due to schema changes.
    – Rick James
    Commented May 4, 2015 at 17:31
  • 4
    After restore you may/will also need flush privileges; on the new mysql. Like mysql -u root -p -e'flush privileges;' This may/will also set your root mysql password on your new server to be the root password from your old server so be sure you know what that is.
    – meesern
    Commented May 31, 2019 at 10:42
0

This PHP script was inspired by the need to do the same thing as the original question where the servers in question were running different version of MariaDB. Since it's PHP it should work on any platform that supports PHP (version 7.3 or higher).

<?php
ini_set('display_errors','1');
ini_set('display_startup_errors','1');
error_reporting(E_ALL);

//
// You will want to modify the 4 variables below for your environment
//

$dbuser       = 'root';                   // DB user with authority to SHOW GRANTS from mysql.user
$dbpassword   = 'blahblah';               // password for the DB user
$useroutfile  = '/temp/Users.sql';        // where to write the user file that may be imported on new server
$grantoutfile = '/temp/Grants.sql';       // where to write the grant file that may be imported on new server
$ignore_users = ['root','replication_user'];  // array of users that should NOT be exported

//
// There really should not be any reason to modify anything below this comment 
// but please do browse through it and understand what is being done
//

$dsn = 'mysql:host=localhost;charset=utf8mb4';
$opt = [PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION ,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC       ,
        PDO::ATTR_EMULATE_PREPARES   => true                   ,
       ];
try {

    $ourdb = new PDO ($dsn,$dbuser,$dbpassword,$opt);

} catch (PDOException $e) {

    error_log($e);  // log the error so it may be looked at later if necessary
    echo 'Could not connect to the SQL server';
    exit;
}  // end of the try/catch block

$notuser = implode(',',array_map('add_quotes',$ignore_users));

//
// We got connected to the database so now let's make sure we can open the
// output files for writing - note that using mode w will overwrite any
// existing files so we'll always start off cleanly
//

$userout = fopen($useroutfile,'w');

if ($userout === false) {  // could not open the output file for writing for some reason

    error_log('Could not open the output file for writing (' . $useroutfile . ')');
    exit;

}  // end of if we could not open the output file for writing

$grantout = fopen($grantoutfile,'w');

if ($grantout === false) {  // could not open the output file for writing for some reason

    error_log('Could not open the output file for writing (' . $grantout . ')');
    exit;

}  // end of if we could not open the output file for writing

$Query = $ourdb->query("
    SELECT CONCAT('SHOW GRANTS FOR ''', user, '''@''', host, ''';') AS query 
           FROM mysql.user 
           WHERE user NOT IN(" . implode(',',array_map('add_quotes',$ignore_users)) . ")
");
$users = $Query->fetchAll(PDO::FETCH_COLUMN);

foreach ($users as $GrantQ) {  // go through each of the users found

    $UserQ  = $ourdb->query("$GrantQ");  // retrieve the grants for a user
    $grants = $UserQ->fetchAll(PDO::FETCH_COLUMN);

    foreach ($grants as $grant) {  // go through each of the grants found for this user

        if (stripos($grant,'IDENTIFIED BY PASSWORD') === false) {

            fwrite($grantout,$grant . ';' . PHP_EOL);  // write the command to actually do the grant

        } else {

            fwrite($userout,$grant . ';' . PHP_EOL);  // write the command to actually do the grant
}
        }  // end of foreach through the grants found

}  // end of foreach through the queries to show the grants for each user

fwrite($userout ,'FLUSH PRIVILEGES;' . PHP_EOL);  // make sure SQL knows about the new users and privileges
fwrite($grantout,'FLUSH PRIVILEGES;' . PHP_EOL);  // make sure SQL knows about the new users and privileges
fclose($userout);   // close our output file
fclose($grantout);  // close our output file
echo 'The grants for ' . count($users) . ' users were written to ' . $useroutfile . PHP_EOL;

function add_quotes($str) {return sprintf("'%s'", $str);}
0

Since mysqlpump is not mentioned here to export users and rights, I will post it since I feel it is the best way of doing this.

Export:

mysqlpump -uroot -p[your password] --host=[your host] --exclude-databases=% --users --exclude-users=root,[other users to exclude] > mysqlusersandgrants.sql

database=% means it won;t export any database

--exclude-users=root,[other users to exclude] is a comma separated list of all the users you don't want to export. You can omit it if you want to export everything.

To Import:

mysql -uroot -p[your password] --host=[your host] mysql < mysqlusersandgrants.sql

Not the answer you're looking for? Browse other questions tagged or ask your own question.