PHP Database Dump Script - есть ли проблемы? - PullRequest
2 голосов
/ 23 июня 2010

Я нашел функцию PHP для вывода базы данных mySQL, которую написал кто-то другой, а затем очистил ее и немного отформатировал.Я хотел знать, смогу ли я получить критику этого.Я запустил его, протестировал в блоге Wordpress, и БД полностью восстановилась, но хотел получить другие взгляды на код.

В частности, я хочу получить отзывы о:

  • Все, что может повредить данные - не может быть сброшено должным образом и т. Д.
  • Нарушение любых передовых методов / принципов
  • Проблемы безопасности
  • Все остальное, что вы можете увидеть как проблему

ПРИМЕЧАНИЕ: я НЕ хочу использовать mysqldump, я хочу полностью сгенерировать эту резервную копию sql из кода.Я также понимаю, что имя файла может быть сгенерировано случайным образом, но файл SQL также будет загружен в Dropbox, и я хочу его версию под тем же именем.

Спасибо!

Код:

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

Ответы [ 6 ]

4 голосов
/ 23 июня 2010

У этого скрипта есть серьезные, разрушающие сделки проблемы.Он не будет работать ни для одной, кроме самой тривиальной базы данных.

  • NULL не поддерживаются.
  • Наборы символов не учитываются.
  • Имена таблиц не принимаютсяс разделителями.
  • Поддерживаются только таблицы - без представлений, хранимых процедур, триггеров, функций и т. д.
  • addslashes() не является безопасным для набора символов .
  • mysql_query() предварительно выбирает все строк таблицы, поэтому, если вы запросите таблицу с миллионами строк, вы превысите предел памяти PHP.Вместо этого используйте mysql_unbuffered_query().Если подумать, я вижу, что вы собираете все выходные данные в $ return, так что это спорный вопрос.
  • Подавление ошибок с помощью оператора @ - плохая практика.Проверяйте на ошибки и терпите неудачу с информативным сообщением.

Ваше требование не использовать mysqldump абсурдно.

Зачем так много работать для себя, изобретаяколесо, и все еще так неправильно?Просто запустите mysqldump через shellexec().


См. Также:

2 голосов
/ 23 июня 2010

Попробуйте mysql команду или mysqldump команду

1 голос
/ 23 июня 2010

В случае, если это очень огромная база данных, которую нужно выгрузить, убедитесь, что на вашем сервере (и на максимальной скорости выполнения php памяти на скрипт) достаточно памяти, чтобы сохранить весь возврат $ в памяти, иначе лучше один раз сбросить файлкакое-то время или каждую строку.

1 голос
/ 23 июня 2010

Это не приведет к сбросу хранимых процедур, функций, представлений, триггеров и т. Д.

Редактировать: Таким же образом вы можете сбросить процедуры и т. Д. Просто используйте то есть SHOW PROCEDURE STATUS; чтобы получить список процедур, а затем SHOW CREATE PROCEDURE для каждой процедуры. То же самое для функций, представлений, триггеров ...

Не забудьте также SHOW CREATE DATABASE;.

1 голос
/ 23 июня 2010

Наборы символов? Возможно, SET NAMES utf8 будет хорошим дополнением.

Кроме того, что произойдет, если база данных содержит представления?

0 голосов
/ 11 апреля 2017

создать резервную копию БД:

<?php

$dbHost = 'DBHOST';
$dbUser = 'DBUSER';
$dbPassword = 'DBPASSWORD';
$dbName = 'DBNAME';
$tables = '*';

backup_tables($dbHost,$dbUser,$dbPassword,$tables);

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

    $db = new PDO("mysql:host=$host;dbname=$name;", $user, $pass);


    //get all of the tables
    if($tables == '*')
    {
        $tables = array();

        $result = $db->query('SHOW TABLES');

        $tables= $result->fetchAll(PDO::FETCH_COLUMN, 0);

    }
    else
    {
        $tables = is_array($tables) ? $tables : explode(',',$tables);
    }

    $return="";

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


        $return.= 'DROP TABLE  IF EXISTS '.$table.';';
        $result=$db->query('SHOW CREATE TABLE '.$table);
        $row2 = $result->fetch(PDO::FETCH_NUM);
        $return.= "\n\n".$row2[1].";\n\n";

        $result = $db->query('SELECT * FROM '.$table);

        foreach ($result->fetchAll(PDO::FETCH_ASSOC) as  $key=>$value) {

            // build query...
           $return .= "INSERT INTO $table (`".implode("`, `", array_keys($value))."`)
            VALUES ('".implode("', '", $value)."');\n\n";

        }

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


    //save file
    $handle = fopen('db-backup-'.date('Y-m-d--H-i-s').'-'.(md5(implode(',',$tables))).'.sql','w+');
    fwrite($handle,$return);
    fclose($handle);
}
...