如何在同一台服务器上复制MySQL数据库

时间:2011-07-11 14:59:09

标签: mysql database sync replicate

我有一个庞大的MySQL数据库,让我们调用它live_db,我想在同一台机器上复制它以提供一个测试系统来解决(test_db),包括表结构和数据。 我定期以test_db的内容更新live_db;如果可能的话增量。

MySQL中是否有一些内置机制可以做到这一点?我认为主从复制不是我想要的,因为它应该可以改变test_db中的数据。但是,不必保留这些更改。

此致

CGD

6 个答案:

答案 0 :(得分:72)

mysql命令行客户端将接受来自标准输入的SQL语句流。因此,您可以在命令行上将mysqldump的输出直接传递到mysql。将此作为cron作业将定期使用更新的实时数据覆盖您的测试数据:

mysql --user=username --password=passwd -e 'DROP DATABASE test_db;'
mysql --user=username --password=passwd -e 'CREATE DATABASE test_db;'
mysqldump --user=username --password=passwd live_db | mysql --user=username --password=passwd test_db

请注意,由于您的数据很大,因此需要很长时间。

答案 1 :(得分:6)

Michaels回答abowe运作良好,但不会复制事件,存储过程或触发器。

要复制那些mysqldump需要更多的开关: --events --triggers --routines

补充已制作的副本:

mysqldump --user=username --password=passwd --no-data --no-create-info --no-create-db --events --triggers --routines live_db | mysql --user=username --password=passwd test_db

答案 2 :(得分:0)

如果您更喜欢MySQL Migration Toolkit,您可以在数据映射步骤中双击模式名称并更改目标模式名称。

答案 3 :(得分:0)

对于所有mac用户,使用sequel pro,您需要做的只是进入数据库(菜单)->复制数据库。完成!

答案 4 :(得分:0)

MySQLdump的问题在于,在转储时,实时数据库要么不可用,要么使用起来很笨拙,否则备份将不一致。除非您有足够宽的时间窗口,否则实时数据库的不可用性并不重要,因为无论如何都不需要使用该数据库(例如深夜)。

如果您有足够的空间来节省空间-如今20 Gb还不足够-使用辅助数据库。

您可以在另一个端口上安装 MySQL Server的第二个副本,并将其作为从属。然后,您将拥有两个相同的数据库(实时主数据库,实时从数据库)。

当您需要克隆测试数据库时,停止从属复制-活动的从属服务器现在将保持“冻结”状态-并使用MySQLbackup或仅复制数据文件将活动的从属服务器备份到测试数据库。完成后,重新启动复制。

对活动主服务器的影响可以忽略不计,从设备实际上可以用于非更新关键的选择。

答案 5 :(得分:-1)

此解决方案可以正常工作,但如果您使用PHPunit进行单元测试,它将无法完成交易。

在命令行中使用密码会生成一个警告,该警告由PHPUnit捕获并生成异常(是非常重要的......)

解决此问题的方法是使用配置文件。

在我的情况下,我不想在配置文件和PHP代码中维护密码和用户,所以我从代码生成配置文件并检查它是否存在(否则我直接使用用户名和密码)命令行作为后退选项)。

以下是一个示例,在PHP中,如何复制安装数据库以创建具有不同名称的新数据库(例如,如果您为每个客户管理具有不同子域/数据库的主域):

/**
* 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;
}

附加说明:

  1. 我必须在我的SQL语句中使用双引号(“)而不是单引号(')。

  2. 我不得不使用&符号(&)分隔我的不同命令。

  3. 此示例不包括新数据库名称的验证(isDestinationDbNameValid()方法)。无需提及您永远不应该信任用户输入......

  4. 您还必须编写自定义方法以验证数据库副本是否按预期工作(isDestinationDbExist()方法)。 您至少应该验证数据库是否存在,您的设置中是否存在表格,并且可以选择验证存储的程序。

  5. 明智地使用武力,我的朋友,

    来自蒙特利尔的Jonathan Parent-Lévesque