4

What i would like to achieve is have two different SQL Server Databases, on two different servers running the same SQL Server Version( SQL Server 2008 R2 RTM - 10.50.1600.1 ) to be synched daily. Synched meaning just transferring the new data ( or even all the data ) from one of the two ("parent" database ) to the other ( "child" database ). We want the parent to force its shema as well all its data to its child.

What i have already tried

Knowing that the two machines run on windows server 2012 R2 i have already tried to implement a solution ( although i am no expert when it comes to SQL Server ) using the following tools.

So what i would do would be this :

  1. Read a configuration file using PHP ( server, user, pass, database, etc.. )
  2. When PHP would not produce any errors i would trigger the schemazen script method.
  3. When everything would go smooth i would trigger the winscp's ftp method to the remote Server

That would be the export Side

Now for the import Side

  1. I would Locate the ftp directory and using the Schemazen create method i would import the data again by reading a configuration file.

Export Side Code

$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;
                }
            }
        }
    }
}

Import Side Code

<?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;
            }
        }
    }
}

The Issue

The big issue is that i developed this testing in my local environment where i am running a different SQL Server Version, and when i tried to test in a staging environment inside the live servers i encountered the following problem https://github.com/sethreno/schemazen/issues/141

I would really appreciate any good alternative ( especially built in tools in SQL Server Managing Studio, but i would need some guidance ) , or any correction that could be applied to the Schemazen since its an open source project to correct the Issue.

Koen Hollander
  • 1,596
  • 6
  • 21
  • 33
  • You seem to be looking for a replication solution. Some of them are open source. Try, for example : https://www.symmetricds.org/about/overview – Marc Guillot Jan 28 '19 at 10:10
  • Thanks a lot Marc, do you happen to know if these replication tools happen to work with Express Versions of SQL Server? – Dimitrios Pantazis Jan 28 '19 at 12:46
  • I haven't tried them on SQL Server, but if they work as they worked with Firebird then yes, they should work with Express Versions. – Marc Guillot Jan 29 '19 at 07:21

2 Answers2

1

Depending upon your requirements you could simply try backup and restore which seems to satisfy your requirement. Alternatively try Replication but that adds considerably to the complexity.

There are also various tools that can do this. If you can pay for them Redgate work pretty well. I'm sure there are also free ones but I don't have experience with them.

I wouldn't recommend rolling your own.

PhilS
  • 624
  • 3
  • 5
  • Thank you very much for your useful answer PhilS. Even though backup and restore would not work for me cause i would like the synchronization to happen automatically, the Replication method seems more than promising! I will try it and let you know about the results! – Dimitrios Pantazis Jan 28 '19 at 10:10
1

There are plenty of options, which I enumerated from easiest to the most complex

  1. Backup with further Restore
  2. Log shipping
  3. Snapshot or Transaction Replications
  4. Database Mirroring

Automation of the first option can be done using command shell: https://blog.sqlauthority.com/2013/02/08/sql-server-backup-and-restore-database-using-command-prompt-sqlcmd/

Some other striking thing: you run RTM version of SQL Server 2008 R2 on servers:

  • It unpatched, Microsoft released 4 service packs. RTM version has severe bugs
  • This version is out support
Alexander Volok
  • 4,970
  • 3
  • 13
  • 30
  • Thanks a lot Alexander for your quick response. First of all i don't have authority over updating any SQL Server version of these machines unfortunately. For your ways of accomplising my goal as i explained i am no expert so i will have to look into some tutorials/documentation in order to verify if they will work for me! Thanks again – Dimitrios Pantazis Jan 28 '19 at 12:45
  • Since your indicated that you a not expert in SQL Server, I can only give an advice to use automated backup and restore. It is pretty simple option. – Alexander Volok Jan 28 '19 at 12:47
  • I have added a link with example of automation. In any case, If you find my answer helpful, please mark it as an answer to your question. – Alexander Volok Jan 28 '19 at 12:50