每天同步不同机器上的两个 SQL 服务器数据库有什么好方法吗?

Is there a good way having two SQL Server Databases on Different machines synched daily?

我想要实现的是有两个不同的 SQL 服务器数据库,在两个 不同的 服务器上 运行 与 相同 SQL 服务器版本 ( SQL Server 2008 R2 RTM - 10.50.1600.1 ) 每天同步。同步意味着只是将新数据(甚至所有数据)从两个("parent" 数据库)之一传输到另一个("child" 数据库)。我们希望父级将其 shema 及其所有数据强制传递给其子级。

我已经尝试过的

知道 windows 服务器 2012 R2 上的两台机器 运行 我已经尝试实施解决方案(虽然我 不是专家 当它来到 SQL 服务器 ) 使用以下工具。

所以我会这样做:

  1. 使用PHP(服务器、用户、密码、数据库等)读取配置文件
  2. 当 PHP 不会产生任何错误时,我会触发 schemazen 脚本方法。
  3. 当一切顺利时,我会触发 winscp 的 ftp 方法到远程服务器

那将是出口方

现在是导入端

  1. 我会找到 ftp 目录并使用 Schemazen 创建方法,我会通过读取配置文件再次导入数据。

导出端代码

$iniConfig = parse_ini_file('..\conf.ini', true);
if ($iniConfig) {
    echo PHP_EOL.'Configuration file found in '.realpath('..\conf.ini').PHP_EOL;
    define('EXPORT_HOST', $iniConfig['export']['host']);
    define('EXPORT_DB', $iniConfig['export']['db']);
    define('EXPORT_DIR', $iniConfig['export']['dir']);
    define('FTP_HOST', $iniConfig['ftp']['host']);
    define('FTP_PATH_TO_SAVE', $iniConfig['ftp']['path']);
    define('FTP_USERNAME', $iniConfig['ftp']['user']);
    define('FTP_PASS', $iniConfig['ftp']['pass']);
    define('PATH_TO_SAVE', $iniConfig['ftp']['path']);

    $output     = [];
    $return_var = 0;
    $credsFlag  = '';

    if ($iniConfig['export']['user'] && $iniConfig['export']['pass']) {
        define('EXPORT_USER', $iniConfig['export']['user']);
        define('EXPORT_PASS', $iniConfig['export']['pass']);
        $credsFlag = ' -u '.EXPORT_USER.' -p '.EXPORT_PASS;
    } else {
        echo PHP_EOL.'Please Define the Username and Password for connection to the Database!'.PHP_EOL;
        die();
    }

    $connArray  = [
        'Database' => EXPORT_DB,
        'UID'      => EXPORT_USER,
        'PWD'      => EXPORT_PASS,
    ];
    $connection = sqlsrv_connect(EXPORT_HOST, $connArray);
    if (!$connection) {
        echo PHP_EOL.'Could not Connect to the Database!' . PHP_EOL . 'We received the following tried to connect:' . PHP_EOL;
        print_r(sqlsrv_errors());
        die();
    }

    $query  = "select table_name from information_schema.tables where table_catalog = '" . EXPORT_DB . "'";
    $tables = [];
    $rs     = sqlsrv_query($connection, $query);
    while (($rd = sqlsrv_fetch_array($rs, SQLSRV_FETCH_ASSOC)) !== false) {
        if ($rd) {
            array_push($tables, $rd);
        }
    }

    sqlsrv_close($connection);
    $dataTablesString = '--dataTables=';
    foreach ($tables as $table) {
        $dataTablesString .= $table['table_name'].',';
    }

    exec('scriptor\SchemaZen.exe script -s '.EXPORT_HOST.' -b '.EXPORT_DB.$credsFlag.' -d '.EXPORT_DIR.' -o '.$dataTablesString, $output, $return_var);
    if (-1 === $return_var) {
        $file = fopen('ftp_script.txt', 'w+');
        if ($file) {
            $ftpStringToWrite = 'open ftp://'.FTP_USERNAME.':'.FTP_PASS.'@'.FTP_HOST.'/'.PHP_EOL.'cd '.FTP_PATH_TO_SAVE.PHP_EOL.'put '.EXPORT_DIR.'\*'.PHP_EOL.'exit';
            $writer           = fwrite($file, $ftpStringToWrite);
            if ($writer) {
                fclose($file);
                unset($output);
                exec('ftp\WinSCP.com /script=ftp_script.txt', $output, $return_var);
                if (0 === $return_var) {
                    echo PHP_EOL.'Backup Exported and Transfered via FTP.'.PHP_EOL;
                }
            }
        }
    }
}

导入端代码

<?php
if ($iniConfig = parse_ini_file('../conf.ini', true)) {
    define('IMPORT_HOST', $iniConfig['import']['host']);
    define('IMPORT_DB', $iniConfig['import']['db']);
    define('IMPORT_DB_AFTER', $iniConfig['settings']['databaseAfterFix']);
    $credsFlags = '';
    if ($iniConfig['import']['user'] && $iniConfig['import']['pass']) {
        define('IMPORT_USER', $iniConfig['import']['user']);
        define('IMPORT_PASS', $iniConfig['import']['pass']);
        $credsFlags = ' -u '.IMPORT_USER.' -p '.IMPORT_PASS;
    } else {
        echo PHP_EOL.'Please Define the Username and Password for connection to the Database!'.PHP_EOL;
        die();
    }
    $output     = [];
    $return_var = 0;
    exec('scriptor\SchemaZen.exe create -s '.IMPORT_HOST.$credsFlags.' -o -b '.IMPORT_DB. ' -d ../../DBMigrate/'.$iniConfig['ftp']['path'].'', $output, $return_var);
    foreach ($output as $message) {
        echo $message.PHP_EOL;
    }
    if (0 !== $return_var) {
        $error_log = fopen($iniConfig['settings']['errorlog'], 'a+');
        if ($error_log) {
            foreach ($output as $error) {
                $writer = fwrite($error_log, '['.date('Y-m-d h:i:s').']'.$error.PHP_EOL);
            }
            $notify = mail($iniConfig['settings']['mail'], 'Import Error Encoutered!', 'Errors in Import of the Server.Please Check an error log should have been Created inside the folder /Data of the importer!');
            if ($notify) {
                echo PHP_EOL.'Mail sent about errors!'.PHP_EOL;
            }
            if ($writer) {
                echo PHP_EOL.'Created Error LOg Please Check!'.PHP_EOL;
            }
        }
    }
}

问题

最大的问题是我在我的本地环境中开发了这个测试,我 运行 宁一个不同的 SQL 服务器版本,当我试图在现场的暂存环境中进行测试时服务器我遇到了以下问题 https://github.com/sethreno/schemazen/issues/141

我真的很感激任何好的替代方案(特别是 SQL Server Managing Studio 中的内置工具,但我需要一些指导),或者任何可以应用于 Schemazen 的更正,因为它是开源的解决问题的项目。

根据您的要求,您可以简单地尝试 backup and restore which seems to satisfy your requirement. Alternatively try Replication,但这会大大增加复杂性。

也有多种工具可以做到这一点。如果你能付钱给他们 Redgate 工作得很好。我敢肯定也有免费的,但我没有使用它们的经验。

我不建议自己滚动。

有很多选择,我从最简单到最复杂列举了这些

  1. 备份并进一步还原
  2. 日志传送
  3. 快照或事务复制
  4. 数据库镜像

第一个选项的自动化可以使用命令 shell 完成: https://blog.sqlauthority.com/2013/02/08/sql-server-backup-and-restore-database-using-command-prompt-sqlcmd/

其他一些引人注目的事情: 您 运行 服务器上 SQL Server 2008 R2 的 RTM 版本:

  • 未打补丁,Microsoft 发布了 4 个服务包。 RTM 版本存在严重错误
  • 此版本不支持