How to duplicate a MySQL database on the same server

前端 未结 6 2048
不知归路
不知归路 2021-01-31 01:51

I have a large MySQL database, lets call it live_db, which I want to replicate on the same machine to provide a test system to play around with (test_db

6条回答
  •  南旧
    南旧 (楼主)
    2021-01-31 02:17

    This solution works fine, but it won't do the deal if you are using PHPunit for unit testing.

    Using password in command line generates a warning which is catch by PHPUnit and generate an exception (yeah quite a big deal...)

    The way to work around this is to use configuration file.

    In my case, I don't want to maintain password and user both in configuration files and PHP code, so I generate the configuration file from the code and check out if it exists (otherwise I use the username and password directly in command line as a fall back option).

    Here's an example, in PHP, how to copy a setup database to create a new one with a different name (if you are, by example, managing a main domain with a different subdomain/database for each of your customer):

    /**
    * If the $dbName doesn't exist, then create it.
    * 
    * @param $errorMessage String to return the error message.
    * @param $dbName String name of the database to create.
    * @param $cleanExisting Boolean if the database exist, clear it to recreate it.
    *
    * @return boolean ($dbExists)
    */
    private function createDatabase(&$errorMessage, $dbName, $clearExisting = false){
    
        $command = "";
        $configurationString = "[client]" . "\r\n" . "user=" . parent::$support_user . "\r\n" . "password=" . md5(parent::$support_pass);
        $dbExist = false;
        $path = realpath(dirname(__FILE__));
    
        $connectionString = " --defaults-extra-file=" . $path . "\mysql.cnf ";
    
        $dbName = strtolower($dbName);
    
        if ($this->isDestinationDbNameValid($errorMessage, $dbName)) {
    
            $dbExist = $this->isDestinationDbExist($errorMessage, $dbName);
    
            if (empty($errorMessage) and ($dbExist === false or $clearExisting === true)) {
    
                if (file_put_contents($path . '/mysql.cnf', $configurationString) === false) {
    
                    $connectionString = " --user=" . parent::$support_user . " --password=" . md5(parent::$support_pass). " ";
                }
    
                if ($dbExist and $clearExisting) {
    
                    $command = $path . '/../../../mysql/bin/mysql ' . $connectionString . ' --execute="DROP DATABASE ' . $dbName  .';" &';
                }
    
                $command .= '"' . $path . '/../../../mysql/bin/mysql" ' . $connectionString . ' --execute="CREATE DATABASE ' . $dbName . ';" &"' .
                            $path . '/../../../mysql/bin/mysqldump" ' . $connectionString . ' --events --triggers --routines setup | "' .
                            $path . '/../../../mysql/bin/mysql" ' . $connectionString . $dbName;
    
                exec($command);
    
                $dbExist = $this->isDestinationDbExist($errorMessage, $dbName);
    
                if (!$dbExist) {
    
                    $errorMessage = parent::getErrorMessage("COPY_SETUP_DB_ERR", "An error occurred during the duplication process of the setup database.");
                }
            }
        }
    
        return $dbExist;
    }
    

    Additional note:

    1. I had to use double quote (") instead of single quote (') around my SQL statements.

    2. I had to use the ampersand (&) to separate my different command.

    3. This example doesn't include the validation for the new database name (isDestinationDbNameValid() method). No need to mention that you should never trust user input...

    4. You also have to write your custom method to validate that the database copy worked as expected (isDestinationDbExist() method). You should at least validate that the database exist, a table from your setup exist and, optionally, validate for stored programs.

    Use the force wisely my friends,

    Jonathan Parent-Lévesque from Montreal

提交回复
热议问题