Почему мой скрипт резервного копирования базы данных не работает в php? - PullRequest
7 голосов
/ 27 июля 2010

Я использую скрипт резервного копирования базы данных Дэвида Уолша (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 / админ / backup.php на линии 18

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

while($row = mysql_fetch_row($result))

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

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

Ответы [ 4 ]

14 голосов
/ 27 июля 2010

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

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

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

  • Это не приведет к правильному утверждению INSERT, если ваша база данных содержит пустые значения.

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

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

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

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

  • 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 Server, но этот пользователь может быть настроен на отсутствие допустимого домашнего каталога. Вам нужен пользователь, у которого есть домашний каталог. Давайте назовем это «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

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

3 голосов
/ 27 июля 2010

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

Обновление

Основная командная строка будет выглядеть так:

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

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

0 голосов
/ 27 июля 2010

Вы должны убедиться, что 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 голосов
/ 27 июля 2010

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

...