【问题标题】:PHP Database Dump Script - are there any issues?PHP 数据库转储脚本 - 有什么问题吗?
【发布时间】:2010-06-23 13:24:16
【问题描述】:

我找到了一个 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);

【问题讨论】:

    标签: php mysql backup database-backups


    【解决方案1】:

    该脚本存在严重的、破坏交易的问题。它不适用于除了最简单的数据库之外的任何数据库。

    • 不支持 NULL。
    • 不考虑字符集。
    • 表名没有分隔。
    • 仅支持表,不支持视图、存储过程、触发器、函数等。
    • addslashes() is not character-set safe
    • mysql_query() 预取 所有 表中的行,因此如果您查询具有数百万行的表,您将超出 PHP 内存限制。请改用mysql_unbuffered_query()。再想一想,我看到你在 $return 中收集了所有输出,所以这没有实际意义。
    • 使用@ 运算符抑制错误是不好的做法。检查错误并优雅地失败并显示信息丰富的消息。

    你不使用mysqldump的要求是荒谬的。

    为什么要为自己重新发明轮子做这么多工作,却仍然犯错?只需通过shellexec() 运行mysqldump。


    另见:

    【讨论】:

      【解决方案2】:

      尝试mysql 命令或mysqldump 命令

      【讨论】:

      • 作者不想使用mysqldump,在问题中说
      【解决方案3】:

      字符集?也许SET NAMES utf8 会是一个很好的补充。

      另外,如果数据库包含视图会怎样?

      【讨论】:

        【解决方案4】:

        如果这是一个需要转储的非常大的数据库,请确保您的服务器(以及每个脚本的 php 最大执行内存)有足够的内存来将整个 $return 保存在内存中,否则您最好一次刷新到文件一会儿,或者每一行。

        【讨论】:

          【解决方案5】:

          这不会转储存储过程、函数、视图、触发器等。

          编辑:您也可以通过这种方式转储程序等。只需使用即SHOW PROCEDURE STATUS; 获取程序列表,然后为每个程序SHOW CREATE PROCEDURE。函数、视图、触发器也是一样的......

          也不要忘记SHOW CREATE DATABASE;

          【讨论】:

            【解决方案6】:

            创建备份数据库:

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

            【讨论】:

              猜你喜欢
              • 2014-06-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-10-23
              • 2012-09-22
              • 1970-01-01
              相关资源
              最近更新 更多