0

私はphpでmysqldbバックアップスクリプトを使用していますが、バックアップには21時間かかります。cliとcronを介して毎日のバックアップスクリプトとして使用したいのですが、皆さんがそれを見て、とにかく最適化できるかどうかを確認できるかどうか疑問に思っていました。

<?

//Timer start
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$start = $time;


ini_set('memory_limit','4000M');
//ini_set('max_execution_time', 300);


$host = "host";
$user = "user";
$pass = "pass";

$db = "tagdb";

$link = mysql_connect($host,$user,$pass);
$result = mysql_query("show databases like 'tag%'");  // we only want tagdb

while($row = mysql_fetch_row($result))
{
    $dbs[] = $row[0];
}

foreach($dbs as $db)
{
        if(strlen($db) == 10 || $db == "tagdb" || $db == "tagui")
        {
        echo $db."\n";
                backup_tables($host,$user,$pass,$db);
    }
}


//backup_tables($host,$username,$password,$db);

/* backup the db OR just a table */
function backup_tables($host,$user,$pass,$name,$tables = '*')
{

      $fname = 'db-backup-'.$name.'_'.time().'.sql'; 
      echo $fname."\n";
      $handle = fopen($fname,'w+');
      $return = '';
      fwrite($handle,$return);
      fclose($handle);

      $link = mysql_connect($host,$user,$pass);
      mysql_select_db($name,$link);

      //get all of the tables
      if($tables == '*')
{
    $tables = array();
    $result = mysql_query('SHOW TABLES');
    while($row = @mysql_fetch_row($result))
    {
        $tables[] = $row[0];
    }
}
else
{
    $tables = is_array($tables) ? $tables : explode(',',$tables);
}

foreach($tables as $table)
{
  $handle = fopen($fname,'a');
  fwrite( $handle, 'DROP TABLE IF EXISTS '.$table.';' );

  $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
  fwrite( $handle, "\n\n".$row2[1].";\n\n" );

  $offset = 10000;

  $start = 0;
  do {
      $result = mysql_query( "SELECT * FROM ".$table." LIMIT ".$start.", ".$offset."" );
      $start += $offset;


      $num_rows = mysql_num_rows( $result );
      if (false === $result) {
        //close original file
        fclose($handle);
        //open error file
        $errfn = $fname.'.ERROR';
        $errf = fopen($errfn,'a');
        $err = mysql_error();
        fwrite( $errf, $err );
        fclose($errf);
        //reopen original file
        $handle = fopen($fname,'a');
        //break loop
        $num_rows = 0;
      }

      while( $row = mysql_fetch_row( $result ) ) {
          $line = 'INSERT INTO '.$table.' VALUES(';
          foreach( $row as $value ) {
              $value = addslashes( $value );
              @$value = ereg_replace( "\n","\\n", $value );
              $line .= '"'.$value.'",';
          }
          $line = substr( $line, 0, -1 ); // cut the final ','
          $line .= ");\n";
          fwrite( $handle, $line );
      }
  } while( $num_rows !== 0 );
  }

  $return="\n\n\n";
  fwrite($handle,$return);
  fclose($handle);
}

//End timer and output time
$time = microtime();
$time = explode(' ', $time);
$time = $time[1] + $time[0];
$finish = $time;
$total_time = round(($finish - $start), 4);
echo "\n Page generated in ".$total_time." seconds. \n";
?>

バックアップを並列プロセスに分割することを考えていましたが、データベースが巨大であり、phpが以前のようにメモリを使い果たすかどうかはわかりません。提案は大歓迎です。

ありがとう!

ps。バックアップを実行するためのより良い方法があることは知っていますが、mysqldumpなどの他のオプションを使用できないため、この特定のスクリプトはうまく機能します。

4

3 に答える 3

6

はい、MySQLでテーブルを直接コピーできます

CREATE TABLE new_table LIKE old_table;
INSERT new_table SELECT * FROM old_table;

それははるかに高速であり、2つの別々のデータベース(NEW_DBとOLD_DB)にテーブルを置くこともできます

CREATE TABLE NEW_DB.new_table LIKE OLD_DB.old_table;
INSERT NEW_DB.new_table SELECT * FROM OLD_DB.old_table;

したがって、PHPにデータを転送せずに、PHPからそれを実行でき、パフォーマンスが大幅に向上します。

于 2012-08-28T20:16:51.340 に答える
2

データベースのバックアップを検討している場合はmysqldump、Dagonが述べたように使用してください。スケジュールに従ってcronタスクから呼び出します。次に、ロールバックする必要がある場合は、適切なダンプ(.sqlファイルに格納されている)を見つけて、ファイルを実行するだけです。

mysqldump -u [username] -p[password] db_name > [timestamped_filename].sql

詳細については、この記事をお読みください

于 2012-08-28T20:20:06.637 に答える
0

mysqldumpを利用していましたが、myisam dbのロックが原因で生産性が低下していることに気付きました。ロックを解除して、使用中にdbをバックアップし続けると、バックアップが使用できなくなりました。そのため、myisamdbsのホットコピーバックアップのようなものが必要です

私が間違っている場合は訂正してください。ただし、スクリプトはまったくロックしません。実行に21時間かかる場合は、同期の問題が発生する必要があります

使用できない場合mysqldump、私が見る唯一の実用的な解決策は、MySQLスレーブを使用することです(http://www.redips.net/mysql/add-new-slave/を参照してください-ポイント1と2があなたの興味を引くものです)およびmysqlhotcopyhttp ://dev.mysql.com/doc/refman/5.1/en/mysqlhotcopy.html 。

最初のソリューションはセットアップがより複雑ですが、実行する方がおそらくよりクリーンで簡単です(また、私は思うに、より高速です)。また、もう少し設定を行うことで、SQLサーバーの負荷分散を兼ねることができます。

于 2012-08-28T21:43:07.907 に答える