简体   繁体   English

PHP数据库转储脚本 - 有什么问题吗?

[英]PHP Database Dump Script - are there any issues?

I found a PHP function to dump a mySQL database that someone else had written, and then cleaned it up and formatted it a bit. 我找到了一个PHP函数来转储其他人编写的mySQL数据库,然后将其清理并格式化了一下。 I wanted to know if I could get a critique of it. 我想知道我是否可以批评它。 I have ran it, tested it on a Wordpress blog and the DB completely restores, but wanted to get some other eyes on the code. 我已经运行它,在Wordpress博客上测试它并且数据库完全恢复,但是想要了解代码。

Specifically I am looking for feedback on: 具体来说,我正在寻找反馈:

  • Anything that could corrupt the data - not properly escaping etc 任何可能破坏数据的东西 - 没有正确逃避等
  • Violating any best practice / principles 违反任何最佳做法/原则
  • Security issues 安全问题
  • Anything else you may see as an issue 您可能会将其他任何问题视为问题

NOTE: I am NOT looking to use mysqldump, I want to completely generate this sql backup from code. 注:我希望用mysqldump,我要彻底从代码中生成这个SQL备份。 I also realize that the filename could be generated randomly, but the SQL file will be uploaded to dropbox as well, and I want to version it under the same name. 我也意识到文件名可以随机生成,但SQL文件也会上传到dropbox,我想用相同的名称对它进行版本控制。

Thanks! 谢谢!

Code: 码:

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

That script has serious, deal-breaking problems. 那个剧本有严重的,破坏性的问题。 It will not work for any but the most trivial database. 除了最琐碎的数据库之外,它不会起作用。

  • NULLs are not supported. 不支持NULL。
  • Character sets are not taken into account. 字符集不予考虑。
  • Table names are not delimited. 表名不是分隔的。
  • Only tables are supported -- not views, stored procedures, triggers, functions, etc. 仅支持表 - 不包括视图,存储过程,触发器,函数等。
  • addslashes() is not character-set safe . addslashes()不是字符集安全的
  • mysql_query() pre-fetches all the rows from the table, so if you query a table with millions of rows, you will exceed your PHP memory limit. mysql_query()预取表中的所有行,因此如果查询具有数百万行的表,则将超出PHP内存限制。 Use mysql_unbuffered_query() instead. 请改用mysql_unbuffered_query() On second thought, I see you collect all the output in $return so this is moot. 第二个想法,我看到你收回$ return中的所有输出,所以这没有实际意义。
  • Your suppression of errors with the @ operator is bad practice. 使用@运算符抑制错误是不好的做法。 Check for errors and fail gracefully with an informative message. 检查错误并使用信息性消息正常失败。

Your requirement not to use mysqldump is absurd. 你不使用mysqldump的要求是荒谬的。

Why make so much work for yourself reinventing the wheel, and still get it so wrong? 为什么要为自己重新制造轮子做这么多工作,但仍然如此错误? Just run mysqldump via shellexec() . 只需通过shellexec()运行mysqldump。


See also: 也可以看看:

尝试使用mysql命令或mysqldump命令

Character sets? 字符集? Perhaps SET NAMES utf8 would be a good addition. 也许SET NAMES utf8会是一个很好的补充。

Also, what happens if the database contains views? 此外,如果数据库包含视图会发生什么?

This will not dump stored procedures, functions, views, triggers and so on. 这不会转储存储过程,函数,视图,触发器等。

Edit: You can dump procedures etc. this way too. 编辑:您也可以通过这种方式转储程序等。 Just use ie SHOW PROCEDURE STATUS; 只需使用ie SHOW PROCEDURE STATUS; to get the list of procedures and then SHOW CREATE PROCEDURE for each procedure. 获取程序列表,然后为每个程序SHOW CREATE PROCEDURE The same thing for functions, views, triggers... 功能,视图,触发器的功能相同......

Don't forget SHOW CREATE DATABASE; 不要忘记SHOW CREATE DATABASE; either. 无论是。

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

create backup DB : 创建备份数据库:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM