柳暗花明笔记

    自写php同步DB之客户端

    所属分类:[ php&web ] 猫哲学家 发表于:2015-03-20 16:11 浏览:836

    <?php

    // Reset error handler
    set_error_handler(array('dbsync_client', 'runtime_error_handler'));

    // Start from cli
    if (PHP_SAPI != 'cli')
    {
    die('Must run with cli mode.');
    }

    // Set params
    $param = array(
    'mysql_bin_path' => '/usr/local/mysql/bin/',
    'success_log' => './client-success.log',
    'error_log' => './client-error.log',
    'shell_log' => './shell.log',
    'tmp_file' => './tmp',
    'server_url' => 'http://domain/server.php',
    'one_import' => 1000,
    'from' => array(
    'host' => 'localhost',
    'user' => 'root',
    'pass' => '123456',
    // 'db' => 'db',
    'db' => array('db1', 'db2'),
    ),
    'to' => array(
    'host' => 'localhost',
    'user' => 'root',
    'pass' => '123456',
    // 'db' => 'db',
    'db' => array('db1', 'db2'),
    ),
    );


    /**
    * Start dbsync
    */
    // One database
    if (!is_array($param['from']['db']))
    {
    // Run dbsync_client
    dbsync_client::run($param);
    }
    // More database
    else
    {
    foreach ($param['from']['db'] as $i => $one_db)
    {
    $tmp_param = $param;
    $tmp_param['from']['db'] = $one_db;
    $tmp_param['to']['db'] = $param['to']['db'][$i];
    // Run dbsync_client
    dbsync_client::run($tmp_param);
    }
    }

    /**
    * Class dbsync_client
    * @anthor Lanmiz 2015-03-10 260177392@qq.com
    */

    class dbsync_client
    {
    public static $error_log_file;

    /**
    * Sync
    * @param $param
    * $param = array(
    * 'from' => array('host'=>'127.0.0.1', 'user'=>'user', 'pass'=>'pass', 'db'=>'db'),
    * 'to' => array('host'=>'127.0.0.1', 'user'=>'user', 'pass'=>'pass', 'db'=>'db'),
    * )
    */
    public static function run($param = array())
    {
    // Set time limit
    set_time_limit(0);

    // Set variable
    $success_log_file = $param['success_log'];
    $error_log_file = $param['error_log'];
    $tmp_file = $param['tmp_file'];
    $mysql_bin_path = $param['mysql_bin_path'];

    self::$error_log_file = $error_log_file;

    $from_db = $param['from'];
    $to_db = $param['to'];

    // Check log file
    if (is_file($success_log_file) and is_writable($success_log_file) and
    is_file($tmp_file) and is_writable($tmp_file) and
    is_file($error_log_file) and is_writable($error_log_file))
    {
    // Do nothing
    }
    else
    {
    self::log($error_log_file, "Check '{$success_log_file}','{$error_log_file}','{$tmp_file}' must exist and writable.");
    exit;
    }

    // Delete all old data (Do not delete because the import include drop sql,haha!!!)
    /*try {

    $delete_result = shell_exec("{$mysql_bin_path}mysqldump -u{$to_db['user']} -p{$to_db['pass']} --no-data --add-drop-table {$to_db['db']} | grep ^DROP | {$mysql_bin_path}mysql -u{$to_db['user']} -p{$to_db['pass']} -v {$to_db['db']}");

    if (empty($delete_result))
    {
    self::log($error_log_file, 'Drop local tables error or no local tables.');
    // exit; // If first local is empty
    }
    else
    {
    self::log($success_log_file, 'Delete local tables ok.');
    }
    }
    catch (Exception $e)
    {
    self::log($error_log_file, $e->getMessage());
    }*/

    // Get all from tables and rows
    $get_tables_data = $from_db;
    $get_tables_data['api'] = 'get_all_tables_and_rows';

    $from_tables = self::request($param['server_url'], 'post', array(), $get_tables_data);

    /*if (empty($from_tables['body']))
    {
    self::log($error_log_file, 'Remote data is empty.');
    exit;
    }*/

    $get_tables = $from_tables['body'];

    if (!isset($get_tables['status']) or $get_tables['status'] != 1)
    {
    self::log($error_log_file, 'Get remote all tables status error.');
    exit;
    }

    self::log($success_log_file, 'Get remote all tables ok.');

    $remote_tables_data = $get_tables['data'];

    if (!is_array($remote_tables_data))
    {
    self::log($error_log_file, 'Remote tables format error.');
    }

    foreach ($remote_tables_data as $one_table)
    {
    try
    {
    file_put_contents($tmp_file, $one_table['created_table']);

    // Import table if error can not receive shell_exec return value
    shell_exec("date >> {$param['shell_log']}");
    shell_exec("{$mysql_bin_path}mysql -u{$to_db['user']} -p{$to_db['pass']} {$to_db['db']} < $tmp_file >> {$param['shell_log']} 2>&1");

    //exec("{$mysql_bin_path}mysql -u{$to_db['user']} -p{$to_db['pass']} {$to_db['db']} < $tmp_file", $o, $n); // if $n===0 is success

    /*if (empty($import_table_result)) // If error can not receive shell_exec return value
    {
    self::log($error_log_file, 'shell_exec import table error.');
    }*/

    // Import data
    for ($i = 0; $i < $one_table['table_rows']; $i += $param['one_import'])
    {
    $get_rows_data = $from_db;
    $get_rows_data['api'] = 'get_table_data_by_page';
    $get_rows_data['table'] = $one_table['table_name'];
    $get_rows_data['rows'] = $param['one_import'];
    $get_rows_data['offset'] = $i;

    sleep(5);
    $get_rows_data = self::request($param['server_url'], 'post', array(), $get_rows_data);

    $rows_data = $get_rows_data['body'];

    if (!isset($rows_data['status']) or $rows_data['status'] != 1)
    {
    self::log($error_log_file, 'Get remote rows error.');
    }

    file_put_contents($tmp_file, $rows_data['data']);

    // Import rows
    shell_exec("{$mysql_bin_path}mysql -u{$to_db['user']} -p{$to_db['pass']} {$to_db['db']} < $tmp_file >> {$param['shell_log']} 2>&1");

    }

    self::log($success_log_file, "Sync db '{$to_db['db']}' table '{$one_table['table_name']}' is ok.");
    }
    catch (Exception $e)
    {
    self::log($error_log_file, $e->getMessage());
    }
    }
    }

    public static function request($url, $m = 'get', $header = array(), $data = NULL)
    {
    try
    {
    $ch = curl_init($url);
    $cookie = 'cookie';

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
    curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);

    curl_setopt($ch, CURLOPT_HEADER, TRUE);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);

    curl_setopt($ch , CURLOPT_COOKIEJAR, $cookie); // get cookie , then sent next request (TODO)

    // Send cookie
    if ($m == 'post') {
    curl_setopt($ch, CURLOPT_POST, 1); // default is get
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // $data array | string
    }

    $response = curl_exec($ch);

    $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    $response_header = substr($response, 0, $header_size);
    $response_body = substr($response, $header_size);

    // For check result is json
    $response_data = json_decode($response_body, 1);
    $json_error = json_last_error();

    if ($json_error != JSON_ERROR_NONE)
    {
    self::log(self::$error_log_file, "Json format error: {$json_error},Remote return:{$response_body}");
    exit;
    }

    return array('header' => $response_header, 'body' => $response_data);
    }
    catch (Exception $e)
    {
    self::log(self::$error_log_file, $e->getMessage());
    exit;
    }
    }

    public static function log($log_file, $mess = '')
    {
    error_log(date('[Y-m-d H:i:s]') . ' ' . print_r($mess, 1) . PHP_EOL, 3, $log_file);
    }

    public function runtime_error_handler($level, $string, $file, $line)
    {
    throw new Exception("{$level}|{$string} in {$file} on line {$line}");
    }
    }

    ?>


    上一编文章 自写php同步DB之服务端 下一编文章 php empty function if undefined variable return true
    最近文章
    发表评论