问题
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. 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.
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. 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.
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);
回答1:
That script has serious, deal-breaking problems. It will not work for any but the most trivial database.
- NULLs are not supported.
- 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.
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. Usemysql_unbuffered_query()
instead. On second thought, I see you collect all the output in $return so this is moot.- 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.
Why make so much work for yourself reinventing the wheel, and still get it so wrong? Just run mysqldump via shellexec().
See also:
- Why is my database backup script not working in php?
回答2:
Try mysql
command or mysqldump
command
回答3:
Character sets? Perhaps SET NAMES utf8
would be a good addition.
Also, what happens if the database contains views?
回答4:
In case this is a very huge database that needs to be dumped, make sure your server (and php max execution memory per script) has enough memory to keep the whole $return in memory, otherwise you better flush to a file once a while, or every line.
回答5:
This will not dump stored procedures, functions, views, triggers and so on.
Edit: You can dump procedures etc. this way too. Just use i.e. SHOW PROCEDURE STATUS;
to get the list of procedures and then SHOW CREATE PROCEDURE
for each procedure. The same thing for functions, views, triggers...
Don't forget SHOW CREATE DATABASE;
either.
回答6:
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);
}
来源:https://stackoverflow.com/questions/3101993/php-database-dump-script-are-there-any-issues