7

我正在使用 David Walsh 的数据库备份脚本(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():提供的参数不是 第18/home5/ideapale/public_html/amatorders_basic/admin/backup.php中的有效 MySQL 结果资源

第 18 行是以下代码:

while($row = mysql_fetch_row($result))

当我在 phpMyAdmin 中运行 SQL(SHOW TABLES) 时,它可以正常工作并向我显示所有表的列表。但由于某种原因,当 php 文件尝试运行 SQL 时,我收到错误消息。

为什么我的数据库备份脚本不起作用?

4

4 回答 4

14

这将无法将您的数据库备份为 SQL 脚本,除非您的数据库只是一个玩具数据库,相当于“hello world”脚本。

那个剧本太骇人听闻了。您不应该使用它来备份数据库。该脚本之前已发布:PHP 数据库转储脚本 - 有什么问题吗?

  • 在 mysql_connect() 或 mysql_queries() 之后没有错误检查。您可能只是输入了错误的密码或其他东西,但您永远不会知道,因为脚本无法验证连接是否成功。

  • 如果您的数据库包含任何 NULL,它将不会产生正确的 INSERT 语句。

  • 不处理字符集。

  • addlashes()不适合转义数据。

  • 表名没有分隔。

  • 不备份视图、过程、函数或触发器。

  • mysql_query() 缓冲结果,因此如果您有一个包含数千行或更多行的表,您将超出 PHP 内存限制。事实上,该脚本将一系列 INSERT 语句连接成一个 PHP 变量。因此,在它完成之前,您将在内存中表示您的整个数据库。

任何人都不应该使用该脚本。 这完全是垃圾,我不会轻易说出来。

只需使用 shellexec() 来运行 mysqldump。

@Álvaro G. Vicario 有一个很好的观点,你甚至不需要使用 PHP 来完成这项任务。我假设您需要从 PHP 脚本进行备份。以下是我从 cron 脚本创建备份的方法:

创建一个shell 脚本,它可以任意调用,例如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 服务器,但这个用户可能被配置为没有有效的主目录。您需要一个具有主目录的用户。我们称之为“我的备份”。

在该用户的主目录下,创建一个.my.cnf包含以下内容的文件:

[mysqldump]
user = alupto_backup
password = xyzzy

其中“alupto_backup”和“xyzzy”是 MySQL 用户名和密码(根据您的环境更改这些)。设置此文件的所有权和模式,以便只有其所有者可以读取它:

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

在这个用户的 home 下创建一个 bin 目录,并将我们的 shell 脚本放入其中。

mkdir ~mybackup/bin
mv mymysqldump ~mybackup/bin

现在您可以运行 shell 脚本来测试它:

sh ~mybackup/bin/mymysqldump

现在为这个用户创建一个 cron 文件:

crontab -u mybackup

@daily ~mybackup/bin/mymysqldump

应该是这样的。

于 2010-07-27T07:08:31.843 回答
3

该脚本看起来很弱恕我直言。您应该考虑使用mysqldump它在您的系统中可用。

更新

基本的命令行是:

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

您可以在本地计算机上测试 mysqldump,一旦您对结果感到满意,就可以创建一个 shell 脚本或直接将其添加为一个 cron 任务。

于 2010-07-27T07:05:04.730 回答
0

使用 mysql_error() 函数查看 MySQL 抱怨的内容。

于 2010-07-27T06:56:16.870 回答
0

您必须确保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
}
于 2010-07-27T06:58:35.390 回答