将MySQL表转移到另一个服务器的最佳实践是什么?

2 投票
5 回答
841 浏览
提问于 2025-04-15 12:29

我有一个系统在一个“主服务器”上,定期将很多信息从MySQL数据库传输到网络上的另一台服务器。

这两台服务器上都运行着MySQL和Apache。我希望能找到一个简单易用的解决方案。

目前我在考虑:

  • XMLRPC
  • RestFul服务
  • 一个简单的POST请求到处理脚本
  • 套接字传输

我主服务器上的应用是一个TurboGears应用,所以我更喜欢“python风格”的,也就是看起来不那么复杂的解决方案。通过FTP或SCP将一个转储的表复制到另一台服务器可能很快,但在我看来,这种方法既快又脏,我希望能有一个更好的解决方案。

有没有人能简单描述一下你们会如何以“最佳实践”的方式来做这件事?

这不一定要涉及数据库。在服务器1上转储表格,并以结构化的方式传输原始数据,这样服务器2就可以处理,而不需要解析太多,也是可以的。不过有一个要求:一旦数据到达服务器2,我希望它能被立即处理,所以在传输完成时必须有某种通知。当然,我可以自己写一个服务器,放在第二台机器上,接受文件并处理等等,但这只是一个非常大的系统中的一小部分,所以我不想花半天时间来实现这个。

谢谢,

汤姆

5 个回答

0

如果你能访问MySQL的数据端口,并且不介意网络上不断传输的数据流量,你可以使用复制功能

1

如果你的表格很小,可以把整个表格发过去,然后在远程服务器上删除旧数据,再插入新数据,这样就有一个简单的通用解决方案:你可以把表格的数据拼成一个长字符串,通过网络服务发送过去。下面是一个实现的例子。需要注意的是,这并不是完美的解决方案,只是我在不同网站之间传输小型简单表格的一种方法:

function DumpTableIntoString($tableName, $includeFieldsHeader = true)
{
  global $adoConn;

  $recordSet = $adoConn->Execute("SELECT * FROM $tableName");
  if(!$recordSet) return false;

  $data = "";

  if($includeFieldsHeader)
  {
    // fetching fields
    $numFields = $recordSet->FieldCount();
    for($i = 0; $i < $numFields; $i++)
      $data .= $recordSet->FetchField($i)->name . ",";
    $data = substr($data, 0, -1) . "\n";
  }

  while(!$recordSet->EOF)
  {
    $row = $recordSet->GetRowAssoc();
    foreach ($row as &$value)
    {
      $value = str_replace("\r\n", "", $value);
      $value = str_replace('"', '\\"', $value);
      if($value == null) $value = "\\N";
      $value = "\"" . $value . "\"";
    }
    $data .= join(',', $row);

    $recordSet->MoveNext();

    if(!$recordSet->EOF)
      $data .= "\n";
  }

  return $data;
}

// NOTE: CURRENTLY FUNCTION DOESN'T SUPPORT HANDLING FIELDS HEADER, SO NOW IT JUST SKIPS IT
// IF NECESSARRY
function FillTableFromDumpString($tableName, $dumpString, $truncateTable = true, $fieldsHeaderIncluded = true)
{
  global $adoConn;

  if($truncateTable)
    if($adoConn->Execute("TRUNCATE TABLE $tableName") === false)
      return false;


  $rows = explode("\n", $dumpString);
  $startRowIndex = $fieldsHeaderIncluded ? 1 : 0;

  $query = "INSERT INTO $tableName VALUES ";
  $numRows = count($rows);

  for($i = $startRowIndex; $i < $numRows; $i++)
  {
    $row = explode(",", $rows[$i]);

    foreach($row as &$value)
    {
      if($value == "\"\\N\"")
        $value = "NULL";
    }

    $query .= "(". implode(",", $row) .")";
    if($i != $numRows - 1)
      $query .= ",";
  }

  if($adoConn->Execute($query) === false)
  {
    return false;
  }

  return true;
}

如果你的表格很大,那我觉得你只需要发送新增的数据。你可以先询问远程服务器最新的数据时间戳,然后从你的主服务器读取所有更新的数据,再以通用的方式(就像我上面展示的那样)或者非通用的方式发送这些数据(在这种情况下,你需要为每个表格写单独的函数)。

2

服务器1:把数据行转换成JSON格式,然后用这些JSON数据去调用第二个服务器的RESTful API。

服务器2:监听一个网址,比如说POST /data,接收JSON数据,然后把它转换回字典或者ORM对象,再插入到数据库里。

你需要用到sqlalchemy/sqlobject和simplejson这两个工具。

撰写回答