Почему мой скрипт резервного копирования базы данных не работает на php?


Я использую сценарий резервного копирования базы данных Дэвида Уолша (http://davidwalsh.name/backup-mysql-database-php ) для резервного копирования моей базы данных MYSQL в виде файла .sql на мой сервер.

Я создал пользователя с именем backup и предоставил ему все права (просто чтобы убедиться). Затем я помещаю код в php-файл и настраиваю задание cron для запуска php-файла.

Это код:

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

    $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);
    }

    //cycle through
    foreach($tables as $table)
    {
        $result = mysql_query('SELECT * FROM '.$table);
        $num_fields = mysql_num_fields($result);

        $return.= 'DROP TABLE '.$table.';';
        $row2 = mysql_fetch_row(mysql_query('SHOW CREATE TABLE '.$table));
        $return.= "\n\n".$row2[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 file
    $handle = fopen('../backup/db-backup-'.time().'-'.(md5(implode(',',$tables))).'.sql','w+');
    fwrite($handle,$return);
    fclose($handle);
}

backup_tables('localhost','alupto_backup','pass','*');

Когда выполняется задание cron, резервное копирование не работает, и я получаю электронное письмо с ошибкой, которая появляется:


Предупреждение: mysql_fetch_row(): предоставленный аргумент не является допустимым ресурсом результатов MySQL в /home5/ideapale/public_html/amatorders_basic/admin/backup.php в режиме онлайн 18

В строке 18 находится этот код:

while($row = mysql_fetch_row($result))

Когда я запускаю SQL (ПОКАЗАТЬ ТАБЛИЦЫ) в phpMyAdmin, он отлично работает и показывает мне список всех таблиц. Но по какой-то причине я получаю сообщение об ошибке, когда файл php пытается запустить SQL.

Почему мой сценарий резервного копирования базы данных не работает?

Author: zeckdude, 2010-07-27

4 answers

Это не поможет создать резервную копию вашей базы данных в виде сценария SQL, если только ваша база данных не является просто игрушечной базой данных, эквивалентом сценария "привет, мир".

Этот сценарий ужасен. Вы не должны использовать его для резервного копирования базы данных. Этот скрипт был опубликован ранее: Скрипт дампа базы данных PHP - есть ли какие-либо проблемы?

  • Нет проверки ошибок после mysql_connect() или mysql_queries(). Вы, вероятно, просто ввели неправильный пароль или что-то в этом роде, но вы бы никогда знайте, потому что сценарий не проверяет, было ли соединение успешным.

  • Это не приведет к правильному оператору ВСТАВКИ, если ваша база данных содержит какие-либо значения NULL.

  • Наборы символов не обрабатываются.

  • Addslashes() не подходит для экранирования данных.

  • Имена таблиц не разделены.

  • Не создает резервные копии представлений, процедур, функций или триггеров.

  • Mysql_query() буферизует результаты, поэтому если у вас есть таблица с тысячами строк или более, вы превысите свой лимит памяти PHP. Фактически, скрипт объединяет серию инструкций INSERT в одну переменную PHP. Таким образом, прежде чем он завершится, в памяти будет представлена вся ваша база данных .

Никто никогда не должен использовать этот скрипт. Это полный мусор, и я не говорю это легкомысленно.

Просто используйте shellexec() для запуска mysqldump.

@Альваро Г.Викарио имеет хороший момент, вам даже не нужно использовать PHP для этой задачи. Я предполагал, что вам нужно сделать резервную копию из PHP-скрипта. Вот как я бы создал резервную копию из скрипта cron:

Создайте сценарий оболочки, его можно назвать как угодно, например mymysqldump.sh . Вот как я бы это написал:

:
: ${BACKUP_HOST:="localhost"}
: ${BACKUP_DATABASE:="mydatabase"}
: ${BACKUP_DIR:="/opt/local/var/db/mysql5/backups"}
: ${BACKUP_FILE:="${DATABASE}-`date +%Y%m%d%H%M%S`"}

mysqldump -h ${BACKUP_HOST} ${BACKUP_DATABASE} > ${BACKUP_DIR}/${BACKUP_FILE}

Конечно, настройте значения переменных так, как это необходимо для вашей среды.

Вы можете заметить, что имя пользователя и пароль отсутствуют в этом файле. Пожалуйста, не вводите пароли в сценарии в виде обычного текста, чтобы каждый мог их прочитать. Вместо этого мы поместим их в файл параметров, чтобы сделать его более безопасным.

Создайте специального пользователя операционной системы, который будет запускать резервное копирование из cron. В вашей системе может быть специальный пользователь "mysql" или "_mysql" для запуска сервера MySQL, но этот пользователь может быть настроен так, чтобы у него не было действительного домашнего каталога. Вам нужен пользователь, у которого есть домашний каталог. Давайте назовем это "mybackup".

Под домом этого пользователя каталог, создайте файл .my.cnf со следующим содержимым:

[mysqldump]
user = alupto_backup
password = xyzzy

Где "alupto_backup" и "xyzzy" - это имя пользователя MySQL и его пароль (измените их для своей среды). Установите владельца и режим этого файла так, чтобы только его владелец мог его прочитать:

chown mybackup .my.cnf
chmod 600 .my.cnf

Создайте каталог bin под домом этого пользователя и поместите в него наш сценарий оболочки.

mkdir ~mybackup/bin
mv mymysqldump ~mybackup/bin

Теперь вы можете запустить сценарий оболочки, чтобы проверить его:

sh ~mybackup/bin/mymysqldump

Теперь создайте файл cron для этого пользователь:

crontab -u mybackup

@daily ~mybackup/bin/mymysqldump

Так и должно быть.

 14
Author: Bill Karwin, 2017-05-23 12:09:12

Сценарий выглядит очень слабым ИМХО. Вам следует рассмотреть возможность использования mysqldump, если он доступен в вашей системе.

Обновление

Основной командной строкой будет:

mysqldump -hYOURHOSTNAME -uYOURUSER -pYOURPASSWORD infocap > dump.sql

Вы можете протестировать mysqldump на своем локальном компьютере и, как только вы будете довольны результатами, либо создайте сценарий оболочки, либо добавьте его непосредственно в качестве задачи cron.

 3
Author: Álvaro González, 2010-07-27 10:02:37

Используйте функцию mysql_error(), чтобы узнать, на что жалуется MySQL.

 0
Author: Mchl, 2010-07-27 06:56:16

Вы должны убедиться, что mysql_query сначала не возвращает непоток. Попробуйте это:

....

if (false !== ($result = mysql_query('SHOW TALBES')) {
    while($row = mysql_fetch_row($result))
    {
        $tables[] = $row[0];
    }
} else {
    // see Mchl's point about mysql_error
}
 0
Author: efritz, 2010-07-27 06:58:35