2

他の誰かが書いた mySQL データベースをダンプする PHP 関数を見つけ、クリーンアップして少しフォーマットしました。私はそれについて批評を得ることができるかどうか知りたかった. 私はそれを実行し、Wordpress ブログでテストし、DB は完全に復元されましたが、コードに別の目を向けたいと思っていました。

具体的には、次の点についてフィードバックを求めています。

  • データを破損する可能性のあるもの - 適切にエスケープしないなど
  • ベストプラクティス/原則への違反
  • セキュリティ上の問題
  • その他、問題と思われるもの

注: mysqldump を使用するつもりはありません。この SQL バックアップをコードから完全に生成したいと考えています。また、ファイル名がランダムに生成される可能性があることも認識していますが、SQL ファイルもドロップボックスにアップロードされるため、同じ名前でバージョンを作成したいと考えています。

ありがとう!

コード:

  // Variables
  $dbHost = 'DBHOST';
  $dbUser = 'DBUSER';
  $dbPassword = 'DBPASSWORD';
  $dbName = 'DBNAME';
  $tables = '*';
  $fileName = 'mydatabase.sql';


  // Logic
    $link = @mysql_connect($dbHost, $dbUser, $dbPassword);
    $db = @mysql_select_db($dbName, $link);

if(!$link || !$db)
 die("Database Error");

//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);


// Loop through tables    
foreach($tables as $table) {

    $result = mysql_query('SELECT * FROM '. $table);
    $num_fields = mysql_num_fields($result);
    $return.= 'DROP TABLE IF EXISTS ' . $table . ';';
  $createTable = mysql_fetch_row(mysql_query('SHOW CREATE TABLE ' . $table));
    $return .= "\n\n" . $createTable[1] . ";\n\n";

    for ($i = 0; $i < $num_fields; $i++) 
    {
        while($row = mysql_fetch_row($result))
        {

            $return.= 'INSERT INTO ' . $table . ' VALUES(';

            for($j = 0; $j < $num_fields; $j++) {

        $row[$j] = addslashes($row[$j]);
        $row[$j] = ereg_replace("\n","\\n", $row[$j]);

        if (isset($row[$j])) { 
          $return .= '"' . $row[$j] . '"' ; 
        } 

        else { 
          $return .= '""'; 
        }

        if ($j < ($num_fields-1)) { 
          $return .= ','; 
        }
            }
            $return .= ");\n";
        }
    }

    $return .="\n\n\n";

}

// Save the file
$handle = fopen($fileName, 'w+');
fwrite($handle, $return);
fclose($handle);
4

6 に答える 6

4

そのスクリプトには、契約を破る深刻な問題があります。最も単純なデータベース以外では機能しません。

  • NULL はサポートされていません。
  • 文字セットは考慮されません。
  • テーブル名は区切りません。
  • ビュー、ストアド プロシージャ、トリガー、関数などではなく、テーブルのみがサポートされます。
  • addslashes()は文字セットセーフではありません
  • mysql_query()テーブルからすべての行をプリフェッチするため、数百万行のテーブルをクエリすると、PHP のメモリ制限を超えてしまいます。mysql_unbuffered_query()代わりに使用してください。よく考えてみると、$return ですべての出力を収集しているので、これは意味がありません。
  • オペレーターでエラーを抑制すること@は悪い習慣です。エラーをチェックし、有益なメッセージで正常に失敗します。

mysqldump を使用しないという要件はばかげています。

車輪を再発明するのに、なぜこれほど多くの労力を費やしているのに、それが間違っているのでしょうか? 経由で mysqldump を実行するだけshellexec()です。


以下も参照してください。

于 2010-06-23T13:49:04.437 に答える
2

mysqlコマンドまたはmysqldumpコマンドを試す

于 2010-06-23T13:27:14.350 に答える
1

これにより、ストアドプロシージャ、関数、ビュー、トリガーなどはダンプされません。

編集:この方法でもプロシージャなどをダンプできます。ieSHOW PROCEDURE STATUS; を使用して手順のリストを取得し、次にSHOW CREATE PROCEDURE各手順を取得します。関数、ビュー、トリガーについても同じです...

どちらかを忘れないでくださいSHOW CREATE DATABASE;

于 2010-06-23T13:37:52.710 に答える
1

これがダンプする必要のある非常に巨大なデータベースである場合は、サーバー(およびスクリプトごとのphp max実行メモリ)に$ return全体をメモリに保持するのに十分なメモリがあることを確認してください。そうでない場合は、ファイルにフラッシュする方がよいでしょう。またはすべての行。

于 2010-06-23T13:41:52.217 に答える
1

文字セット?おそらくSET NAMES utf8良い追加になるでしょう。

また、データベースにビューが含まれている場合はどうなりますか?

于 2010-06-23T13:31:23.300 に答える