5

这个函数在这里 http://davidwalsh.name/backup-mysql-database-php

已经在互联网上流传了一段时间并且非常有名,但它使用的是旧的 MySQL API。有没有人有相同的但在 PDO 中?如果没有,有人想做一个吗?

是否有可能,我在某处读到 PDO 不执行 SHOW CREATE TABLE - 对吗?

4

7 回答 7

9

那个备份脚本很荒谬,没有人应该制作另一个版本。我以前看过那个脚本,也有类似的尝试,但他们有很多问题:

  • 不在反引号中分隔表名
  • 不处理 NULL
  • 不处理字符集
  • 不处理二进制数据
  • 不备份 VIEW
  • 不备份触发器或存储过程或存储函数或事件
  • 使用过时的 mysql 扩展(但这就是您想要 PDO 版本的原因,不是吗?)
  • 使用 addlashes() 而不是正确的 MySQL 转义函数。
  • 在输出整个内容之前,将所有表的所有数据附加到一个非常长的字符串中。这意味着您必须能够将整个数据库存储在一个字符串中,这几乎肯定会超出您的 PHP 最大内存限制。

另请参阅我过去对不幸的 David Walsh 备份脚本的回答:


回复您的评论:

阅读您链接到的页面上的评论。很多人已经发现了问题,有些人已经修复或至少提出了建议。

我认为这个脚本将所有内容附加到一个字符串中的事实是一个交易破坏者,但更改脚本以首先打开输出文件,然后在循环期间输出每一行的数据,然后关闭文件应该不难循环之后。这很简单,我不确定为什么脚本不这样做。但很明显,该脚本没有经过很好的测试。

但无论如何,我不会试图重新发明这个轮子。Mysqldump 或 mydumper 可以很好地完成这项工作。FWIW,您不必在数据库所在的同一台服务器上运行 mysqldump 。Mysqldump 支持一个选项,--host因此您可以在任何地方运行 mysqldump 来备份远程数据库,只要防火墙不阻止您的客户端连接。基本上,如果您可以从某个客户端主机将 PHP 应用程序连接到数据库,则可以连接 mysqldump。

如果这真的不是一个选项,那么我会使用 phpmyadmin 的数据库转储功能。这些都是成熟且经过充分测试的,它们可以正确地转储所有内容。这是一篇描述如何使用转储功能的文章:

http://www.techrepublic.com/blog/smb-technologist/import-and-export-databases-using-phpmyadmin/


[从您的回答中复制我的评论:]

这是进入代码审查,这不是 StackOverflow 的目的。但简而言之:

  • 对 NULL 没有适当的支持(您将它们转换为 '');
  • 没有一致地分隔表名;
  • 使用非 ANSI 双引号作为字符串分隔符;
  • 在大表上使用缓冲查询将打破 PHP 最大内存限制;
  • 为一个巨大的表附加所有行将打破 PHP 最大内存限制;
  • 使用 addlashes() 代替 PDO::quote();
  • 仅在函数结束时检查查询错误;
  • 不检查文件创建失败;
  • gzip 扩展可能无法加载
  • 此外,可能仍然不支持 UTF8 数据。

但它正在到达那里,不是吗?

是的,这比原来的大卫沃尔什剧本要好。:-)

NULL 到 '' 有什么问题?

NULL 与 SQL 中的 '' 不同(Oracle 除外,但在这种情况下它们不符合 SQL 标准)。查看MySQL,最好插入 NULL 或空字符串?

表结构必须非常大才能最大内存。每个插入行都单独写入文件,因此,对于最大内存,行必须非常大。

我误读了有关内存限制问题的代码。您正在为每一行编写输出,所以没关系(除非该行包含 1GB 的 blob 或其他东西)。

但是您不应该只输出带有逗号分隔的行集的单个 INSERT 语句。甚至mysqldump --extended-insert输出有限长度的数据,然后开始一个新的 INSERT 语句。标准是 INSERT 语句的长度是否适合 的选项参数--net-buffer-length

“”字符串分隔符有什么问题?我如何获得 ANSI 的?

在 ANSI SQL 中,单引号 '' 用于分隔字符串文字或日期文字。双引号“”用于分隔标识符,如表名或列名。默认情况下,MySQL 将它们视为相同,但这是非标准的。请参阅不同的数据库是否使用不同的名称引用?. 如果您尝试在您拥有的 MySQL 服务器上导入备份数据SET SQL_MODE=ANSI_QUOTES,则导入将失败。

哪些表格没有分隔?

示例:query('SELECT * FROM '.$table);实际上,您在查询中使用 $table 的其他每种情况。在脚本输出的 INSERT 语句中,您只对表进行了一次分隔。

所有的 $tables 都没有分隔,它们都需要用“”吗?

MySQL 总是将反引号识别为标识符分隔符,并将单引号识别为字符串/日期。但是双引号会根据我提到的 SQL_MODE 改变含义。您不能假设哪个 SQL_MODE 对您还原的 MySQL 实例有效,因此最好使用反引号作为标识符,使用单引号作为字符串。您在查询表时对它们进行分隔的原因是您的表名可能是 SQL 保留字或包含特殊字符等。

你可以在mysql中插入不带分隔符的浮点数,还是需要''?谢谢

您可以插入所有没有分隔符的数字类型。只有字符串和日期需要分隔符。见 dev.mysql.com/doc/refman/5.6/en/literals.html

于 2013-08-16T20:31:32.513 回答
9

对于任何寻找类似于 mysqldump 的功能的人,这里是最新的草案,上面/下面的评论中讨论的缺陷已经解决。

require 'login.php';
$DBH = new PDO("mysql:host=$db_hostname;dbname=$db_database; charset=utf8", $db_username, $db_password);

//put table names you want backed up in this array.
//leave empty to do all
$tables = array();

backup_tables($DBH, $tables);

function backup_tables($DBH, $tables) {
    $DBH->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL);

    //Script Variables
    $compression = false;
    $BACKUP_PATH = "";
    $nowtimename = time();

    //create/open files
    if ($compression) {
        $zp = gzopen($BACKUP_PATH . $nowtimename . '.sql.gz', "a9");
    } else {
        $handle = fopen($BACKUP_PATH . $nowtimename . '.sql', 'a+');
    }

    //array of all database field types which just take numbers
    $numtypes = array('tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal', 'real');

    //get all of the tables
    if (empty($tables)) {
        $pstm1 = $DBH->query('SHOW TABLES');
        while ($row = $pstm1->fetch(PDO::FETCH_NUM)) {
            $tables[] = $row[0];
        }
    } else {
        $tables = is_array($tables) ? $tables : explode(',', $tables);
    }

    //cycle through the table(s)

    foreach ($tables as $table) {
        $result = $DBH->query("SELECT * FROM $table");
        $num_fields = $result->columnCount();
        $num_rows = $result->rowCount();

        $return = "";
        //uncomment below if you want 'DROP TABLE IF EXISTS' displayed
        //$return.= 'DROP TABLE IF EXISTS `'.$table.'`;';

        //table structure
        $pstm2 = $DBH->query("SHOW CREATE TABLE $table");
        $row2 = $pstm2->fetch(PDO::FETCH_NUM);
        $ifnotexists = str_replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $row2[1]);
        $return .= "\n\n" . $ifnotexists . ";\n\n";

        if ($compression) {
            gzwrite($zp, $return);
        } else {
            fwrite($handle, $return);
        }
        $return = "";

        //insert values
        if ($num_rows) {
            $return = 'INSERT INTO `' . $table . '` (';
            $pstm3 = $DBH->query("SHOW COLUMNS FROM $table");
            $count = 0;
            $type = array();

            while ($rows = $pstm3->fetch(PDO::FETCH_NUM)) {
                if (stripos($rows[1], '(')) {
                    $type[$table][] = stristr($rows[1], '(', true);
                } else {
                    $type[$table][] = $rows[1];
                }

                $return .= "`" . $rows[0] . "`";
                $count++;
                if ($count < ($pstm3->rowCount())) {
                    $return .= ", ";
                }
            }

            $return .= ")" . ' VALUES';

            if ($compression) {
                gzwrite($zp, $return);
            } else {
                fwrite($handle, $return);
            }
            $return = "";
        }
        $count = 0;
        while ($row = $result->fetch(PDO::FETCH_NUM)) {
            $return = "\n\t(";

            for ($j = 0; $j < $num_fields; $j++) {

                //$row[$j] = preg_replace("\n","\\n",$row[$j]);

                if (isset($row[$j])) {

                    //if number, take away "". else leave as string
                    if ((in_array($type[$table][$j], $numtypes)) && (!empty($row[$j]))) {
                        $return .= $row[$j];
                    } else {
                        $return .= $DBH->quote($row[$j]);
                    }
                } else {
                    $return .= 'NULL';
                }
                if ($j < ($num_fields - 1)) {
                    $return .= ',';
                }
            }
            $count++;
            if ($count < ($result->rowCount())) {
                $return .= "),";
            } else {
                $return .= ");";
            }
            if ($compression) {
                gzwrite($zp, $return);
            } else {
                fwrite($handle, $return);
            }
            $return = "";
        }
        $return = "\n\n-- ------------------------------------------------ \n\n";
        if ($compression) {
            gzwrite($zp, $return);
        } else {
            fwrite($handle, $return);
        }
        $return = "";
    }

    $error1 = $pstm2->errorInfo();
    $error2 = $pstm3->errorInfo();
    $error3 = $result->errorInfo();
    echo $error1[2];
    echo $error2[2];
    echo $error3[2];

    if ($compression) {
        gzclose($zp);
    } else {
        fclose($handle);
    }
}
于 2013-08-18T01:07:56.973 回答
4

根据https://stackoverflow.com/a/18281687/2259391mysqldump的建议,使用exec. 归结为:

<?php

function importDatabase($host, $user, $password, $database, $backupFilePath)
{
    //returns true iff successfull
    return exec('mysqlimport --host '. $host .' --user '. $user .' --password '. $password .' '. $database .' '.targetFilePath) === 0;
}

function exportDatabase($host, $user, $password, $database, $targetFilePath)
{
    //returns true iff successfull
    return exec('mysqldump --host '. $host .' --user '. $user .' --password '. $password .' '. $database .' --result-file='.targetFilePath) === 0;
}
于 2015-07-05T18:11:12.063 回答
3

All PDOand ext/mysqldo 都是将命令包装到底层数据库(在本例中为 MySQL)。也就是说,没有什么可以停止PDO运行SHOW CREATE TABLE或其他命令。

出于所有意图和目的,您几乎可以替换:

- $link = mysql_connect($host,$user,$pass);
- mysql_select_db($name,$link);
+ $link = new PDO("mysql:host=$host;dbname=$name", $user, $pass);

而不是

$result = mysql_query($query);
mysql_fetch_assoc($result);

利用

$result = $link->query($query);
$result->fetch();
于 2013-08-16T17:42:45.520 回答
1

我刚刚完成了大卫沃尔什原始备份功能的PDO版本。
我还对其进行了改进以解决Bill Karwin 的回答中提到的问题;处理 NULL,写入单独的行,因此没有内存问题,带有反引号等。
给出了 mysqldump 所做的几乎完全一样的事情。
可以做一点整理,但在这里,请就任何改进提出建议

require 'login.php';
$DBH = new PDO("mysql:host=$db_hostname;dbname=$db_database; charset=utf8", $db_username, $db_password);




//put table names you want backed up in this array.
//leave empty to do all
$tables = array();

backup_tables($DBH, $tables);



function backup_tables($DBH, $tables) {

$DBH->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_TO_STRING );

//Script Variables
$compression = false;
$BACKUP_PATH = "";
$nowtimename = time();


//create/open files
if ($compression) {
$zp = gzopen($BACKUP_PATH.$nowtimename.'.sql.gz', "w9");
} else {
$handle = fopen($BACKUP_PATH.$nowtimename.'.sql','a+');
}


//array of all database field types which just take numbers 
$numtypes=array('tinyint','smallint','mediumint','int','bigint','float','double','decimal','real');

//get all of the tables
if(empty($tables)) {
$pstm1 = $DBH->query('SHOW TABLES');
while ($row = $pstm1->fetch(PDO::FETCH_NUM)) {
$tables[] = $row[0];
}
} else {
$tables = is_array($tables) ? $tables : explode(',',$tables);
}

//cycle through the table(s)

foreach($tables as $table) {
$result = $DBH->query('SELECT * FROM '.$table);
$num_fields = $result->columnCount();
$num_rows = $result->rowCount();

$return="";
//uncomment below if you want 'DROP TABLE IF EXISTS' displayed
//$return.= 'DROP TABLE IF EXISTS `'.$table.'`;'; 


//table structure
$pstm2 = $DBH->query('SHOW CREATE TABLE '.$table);
$row2 = $pstm2->fetch(PDO::FETCH_NUM);
$ifnotexists = str_replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $row2[1]);
$return.= "\n\n".$ifnotexists.";\n\n";


if ($compression) {
gzwrite($zp, $return);
} else {
fwrite($handle,$return);
}
$return = "";

//insert values
if ($num_rows){
$return= 'INSERT INTO `'.$table."` (";
$pstm3 = $DBH->query('SHOW COLUMNS FROM '.$table);
$count = 0;
$type = array();

while ($rows = $pstm3->fetch(PDO::FETCH_NUM)) {

if (stripos($rows[1], '(')) {$type[$table][] = stristr($rows[1], '(', true);
} else $type[$table][] = $rows[1];

$return.= $rows[0];
$count++;
if ($count < ($pstm3->rowCount())) {
$return.= ", ";
}
}

$return.= ")".' VALUES';

if ($compression) {
gzwrite($zp, $return);
} else {
fwrite($handle,$return);
}
$return = "";
}

while($row = $result->fetch(PDO::FETCH_NUM)) {
$return= "\n\t(";
for($j=0; $j<$num_fields; $j++) {
$row[$j] = addslashes($row[$j]);
//$row[$j] = preg_replace("\n","\\n",$row[$j]);


if (isset($row[$j])) {
//if number, take away "". else leave as string
if (in_array($type[$table][$j], $numtypes)) $return.= $row[$j] ; else $return.= '"'.$row[$j].'"' ;
} else {
$return.= '""';
}
if ($j<($num_fields-1)) {
$return.= ',';
}
}
$count++;
if ($count < ($result->rowCount())) {
$return.= "),";
} else {
$return.= ");";

}
if ($compression) {
gzwrite($zp, $return);
} else {
fwrite($handle,$return);
}
$return = "";
}
$return="\n\n-- ------------------------------------------------ \n\n";
if ($compression) {
gzwrite($zp, $return);
} else {
fwrite($handle,$return);
}
$return = "";
}



$error1= $pstm2->errorInfo();
$error2= $pstm3->errorInfo();
$error3= $result->errorInfo();
echo $error1[2];
echo $error2[2];
echo $error3[2];

if ($compression) {
gzclose($zp);
} else {
fclose($handle);
}
}
于 2013-08-17T14:28:43.407 回答
0
function backupDB()
{
    $db_config = getDbConfigFromWordPress();
    if ($db_config === false) {
        unset($db_config);
        logMessage('Unable to get database configuration from WordPress', true, 'red');
        return false;
    }

    $new_backup_file = __DIR__ . DIRECTORY_SEPARATOR . 'newbackup_xxx_date.sql';
    if (is_file($new_backup_file) && is_writable($new_backup_file)) {
        @unlink($new_backup_file);
    } elseif (is_file($new_backup_file) && !is_writable($new_backup_file)) {
        logMessage('Unable to remove new backup SQL file. This is necessary to create backup SQL file.', true, 'red');
        return false;
    }
    unset($new_backup_file);

    $dbh = new \PDO('mysql:dbname=' . $db_config['dbname'] . ';host=' . $db_config['dbhost'] . ';charset=' . $db_config['dbcharset'], $db_config['dbuser'], $db_config['dbpassword']);
    $dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
    $dbh->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);
    $dbh->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);

    $sth = $dbh->prepare('SHOW TABLES');
    $sth->execute();
    $result = $sth->fetchAll(\PDO::FETCH_COLUMN);
    $tables = [];
    if (is_array($result) && !empty($result)) {
        foreach ($result as $row) {
            if (is_string($row) && stristr($row, $db_config['tableprefix']) !== false) {
                $tables[] = $row;
            } elseif (is_array($row) && array_key_exists(0, $row) && stristr($row[0], $db_config['tableprefix']) !== false) {
                $tables[] = $row[0];
            }
        }// endforeach;
        natcasesort($tables);
    }
    $sth->closeCursor();
    unset($result, $row, $sth);

    // begins export string header.
    $export_sql = '-- Manual backup SQL Dump'."\n\n";
    $export_sql .= 'SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";'."\n\n\n";
    $export_sql .= '--'."\n";
    $export_sql .= '-- Database: `' . $db_config['dbname'] . '`'."\n";
    $export_sql .= '--'."\n\n";
    unset($db_config);
    writeDownBackupDB($export_sql);
    unset($export_sql);

    // starting to loop thru tables.
    if (isset($tables) && is_array($tables)) {
        foreach ($tables as $table) {
            $export_sql = '-- --------------------------------------------------------'."\n\n";
            $export_sql .= '--'."\n";
            $export_sql .= '-- Table structure for table `' . $table . '`'."\n";
            $export_sql .= '--'."\n\n";
            $export_sql .= 'DROP TABLE IF EXISTS `' . $table . '`;'."\n";
            $sth = $dbh->prepare('SHOW CREATE TABLE `' . $table . '`');
            $sth->execute();
            $row = $sth->fetch(\PDO::FETCH_NUM);
            if (isset($row[1])) {
                $create_sql_string = $row[1];
                $create_sql_string = str_replace(['CREATE TABLE `'], ['CREATE TABLE IF NOT EXISTS `'], $create_sql_string);
                if (substr($create_sql_string, -1) != ';') {
                    $create_sql_string .= ' ;';
                }
            } else {
                $create_sql_string = '';
            }
            unset($row);
            $export_sql .= $create_sql_string."\n\n";
            $sth->closeCursor();
            unset($sth);
            writeDownBackupDB($export_sql);
            unset($export_sql);

            $export_sql = '--'."\n";
            $export_sql .= '-- Dumping data for table `' . $table . '`'."\n";
            $export_sql .= '--'."\n\n";
            writeDownBackupDB($export_sql);
            unset($export_sql);

            // get fields
            $sth = $dbh->prepare('SELECT * FROM `' . $table . '` LIMIT 1');
            $sth->execute();
            $result = $sth->fetch(\PDO::FETCH_ASSOC);
            if (is_array($result)) {
                $fields = array_keys($result);
            } else {
                $fields = [];
            }
            $sth->closeCursor();
            unset($result, $sth);

            // get fields type
            $sth = $dbh->prepare('DESCRIBE `' . $table . '`');
            $sth->execute();
            $table_columns = $sth->fetchAll();
            $columns = [];
            if (is_array($table_columns)) {
                foreach ($table_columns as $column) {
                    $columns[$column->Field] = [
                        'field' => $column->Field,
                        'type' => $column->Type,
                        'null' => $column->Null,
                        'default' => $column->Default,
                    ];
                }// endforeach;
                unset($column);
            }
            $sth->closeCursor();
            unset($sth, $table_columns);

            if (isset($fields) && is_array($fields) && !empty($fields)) {
                $select_string = 'SELECT ';
                $i_count_field = 1;
                foreach ($fields as $field) {
                    $select_string .= 'IF (`' . $field . '` IS NULL, \'FIELD_VALUE_NULL\', `' . $field . '`) AS `' . $field . '`';
                    if ($i_count_field < count($fields)) {
                        $select_string .= ', ';
                    }
                    $i_count_field++;
                }// endforeach;
                unset($i_count_field, $field);
                $select_string .= ' FROM `' . $table . '`';
                $sth = $dbh->prepare($select_string);
                unset($select_string);
                $sth->execute();
                $result = $sth->fetchAll();
                $export_sql = '';
                if (is_array($result) && !empty($result)) {
                    // generate INSERT INTO `table_name` string.
                    $export_sql .= 'INSERT INTO `' . $table . '` (';
                    $i_count = 1;
                    foreach ($fields as $field) {
                        $export_sql .= '`' . $field . '`';
                        if ($i_count < count($fields)) {
                            $export_sql .= ', ';
                        }
                        $i_count++;
                    }// endforeach;
                    unset($field, $i_count);
                    $export_sql .= ') VALUES'."\n";
                    writeDownBackupDB($export_sql);
                    unset($export_sql);

                    // generate VALUES of INSERT INTO.
                    if (is_array($result)) {
                        $i_count = 1;
                        $i_count_break = 1;
                        foreach ($result as $row) {
                            $export_sql = '(';
                            $i_count_fields = 1;
                            foreach ($fields as $field) {
                                $field_value = $row->{$field};
                                // escape slash
                                $field_value = str_replace('\\', '\\\\', $field_value);
                                // sanitize new line
                                $field_value = str_replace(["\r\n", "\r", "\n"], ['\r\n', '\r', '\n'], $field_value);
                                // escape single quote
                                $field_value = str_replace('\'', '\'\'', $field_value);
                                // change value to NULL if it is NULL.
                                if ($field_value === 'FIELD_VALUE_NULL') {
                                    $field_value = 'NULL';
                                }

                                // detect field value type and cloak with single quote.
                                if (isset($columns[$field]['type']) && 
                                    (
                                        stristr($columns[$field]['type'], 'tinyint(') !== false ||
                                        stristr($columns[$field]['type'], 'smallint(') !== false ||
                                        stristr($columns[$field]['type'], 'mediumint(') !== false ||
                                        stristr($columns[$field]['type'], 'int(') !== false ||
                                        stristr($columns[$field]['type'], 'bigint(') !== false
                                    )
                                ) {
                                    // this field column type is int
                                    if (!is_numeric($field_value) && $field_value !== 'NULL') {
                                        $field_value = '\'' . $field_value . '\'';
                                    }
                                } else {
                                    if ($field_value !== 'NULL') {
                                        $field_value = '\'' . $field_value . '\'';
                                    }
                                }

                                $export_sql .= $field_value;
                                unset($field_value);

                                if ($i_count_fields < count($fields)) {
                                    $export_sql .= ', ';
                                }
                                $i_count_fields++;
                            }// endforeach;
                            unset($field, $i_count_fields);
                            $export_sql .= ')';

                            if ($i_count < count($result)) {
                                if ($i_count_break >= 30) {
                                    $export_sql .= ';'."\n";
                                    writeDownBackupDB($export_sql);
                                    unset($export_sql);
                                    $i_count_break = 0;

                                    $export_sql = 'INSERT INTO `' . $table . '` (';
                                    $i_count_fields = 1;
                                    foreach ($fields as $field) {
                                        $export_sql .= '`' . $field . '`';
                                        if ($i_count_fields < count($fields)) {
                                            $export_sql .= ', ';
                                        }
                                        $i_count_fields++;
                                    }// endforeach;
                                    unset($field, $i_count_fields);
                                    $export_sql .= ') VALUES'."\n";
                                    writeDownBackupDB($export_sql);
                                    unset($export_sql);
                                    $export_sql = '';
                                } else {
                                    $export_sql .= ','."\n";
                                }
                            } else {
                                $export_sql .= ';'."\n\n";
                            }
                            $i_count++;
                            $i_count_break++;
                            writeDownBackupDB($export_sql);
                            unset($export_sql);
                        }// endforeach;
                        unset($i_count, $i_count_break, $result, $row);
                    }
                } else {
                    $export_sql .= "\n";
                    writeDownBackupDB($export_sql);
                    unset($export_sql);
                }
                unset($fields);
                $sth->closeCursor();
                unset($result, $sth);
            } else {
                $export_sql = "\n";
                writeDownBackupDB($export_sql);
                unset($export_sql);
            }
            unset($export_sql);
        }// endforeach;
        unset($table);
    }
    unset($tables);

    unset($dbh);
    logMessage('Backup DB completed. Max memory usage is ' . formatBytes(memory_get_peak_usage(true)) . '.', true, 'green');
    return true;
}// backupDB


/**
 * Write content to backup SQL file by append.
 * 
 * @param string $content
 */
function writeDownBackupDB($content)
{
    $new_backup_file = __DIR__ . DIRECTORY_SEPARATOR . 'newbackup_xxx_date.sql';
    $handle = fopen($new_backup_file, 'a+');
    fwrite($handle, $content);
    fclose($handle);
    unset($handle, $new_backup_file);
}// writeDownBackupDB


logMessage('Beginning backup DB.', true, 'light_gray');
backupDB();

请注意...

  1. 缺少某些功能,例如logMessage(), getDbConfigFromWordPress()。请在使用前删除。
  2. 类似$db_config['tableprefix']$db_config[...]必须改变的东西。
  3. 正如@Bill Karwin所说,有很多事情无法处理。
  4. 我不确定它是否支持 UTF-8 数据,但正如我所见,它支持多种语言并且还支持 emoji ()。
  5. 使用 mysql 命令导出总是更好的主意。
于 2017-01-18T10:44:26.470 回答
0

我通过一些修改实现了 Lan 的最新版本(见下面的代码):

  • 表格保存在名称为今天日期的文件夹中;同一天的先前版本被覆盖
  • 它支持多种格式,包括逗号分隔的 CSV
  • 它以字节和行数显示表格大小
  • 使用我的(诚然过时的)表格

添加 csv 选项的一个原因是,当它是多字节(亚洲脚本)时,我发现无法从 TEXT(UTF8)格式的 sql 文件中导入数据。它确实适用于 BLOB 格式,但是我们不能将其索引为 FULLTEXT。我可能错过了格式化表格的一点......

无论如何,这是代码:

function backup_tables($DBH,$tables,$compression,$format) {
$DBH->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_NATURAL );
//Script Variables
$BACKUP_PATH = DUMP;
$date = date("Y-m-d");
$olddir =  getcwd();
chdir($BACKUP_PATH);
if(!file_exists($date)) {
    echo "<font color=red>Created ‘".$date."’ folder</font><br />";
    $cmd = "mkdir ".$date;
    exec($cmd);
    }
chdir($date);

//array of all database field types which just take numbers 
$numtypes = array('tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal', 'real');

//get all of the tables
if(empty($tables)) {
    $pstm1 = $DBH->query('SHOW TABLES');
    while($row = $pstm1->fetch(PDO::FETCH_NUM)) {
        $tables[] = $row[0];
        }
    }
else {
    $tables = is_array($tables) ? $tables : explode(',',$tables);
    }

//cycle through the table(s)
echo "<font color=blue>Dumping tables to DB_DUMP:</font>";
echo "<ul>";
foreach($tables as $table) {
    //create/open files
    if($format == "csv") {
        $filename = $table.".csv";
        $handle = fopen($filename,"w");
        }
    else {
        if($compression) {
            $filename = $table.".sql.gz";
            $zp = gzopen($filename,"wb9");
            }
        else {
            $filename = $table.".sql";
            $handle = fopen($filename,"w");
            }
        }
    echo "<li><small><font color=blue>".$filename."</font>";
    $result = $DBH->query("SELECT * FROM $table");
    $num_fields = $result->columnCount();
    $num_rows = $result->rowCount();
    $return = "";
    $return .= 'DROP TABLE IF EXISTS `'.$table.'`;'; 

    //table structure
    $pstm2 = $DBH->query("SHOW CREATE TABLE $table");
    $row2 = $pstm2->fetch(PDO::FETCH_NUM);
    $ifnotexists = str_replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS', $row2[1]);
    $return .= "\n\n".$ifnotexists.";\n\n";

    if($format <> "csv") {
        if($compression) gzwrite($zp, $return);
        else fwrite($handle,$return);
        }
    $return = "";

    //insert values
    if($num_rows) {
        $return = 'INSERT INTO `'."$table"."` (";
        $pstm3 = $DBH->query("SHOW COLUMNS FROM $table");
        $count = 0;
        $type = array();

        while($rows = $pstm3->fetch(PDO::FETCH_NUM)) {
            if(stripos($rows[1], '(')) {
                $type[$table][] = stristr($rows[1], '(', true);
                }
            else $type[$table][] = $rows[1];

            $return .= "`".$rows[0]."`";
            $count++;
            if($count < ($pstm3->rowCount())) {
                $return .= ", ";
                }
            }
        $return .= ")".' VALUES';
        if($format <> "csv") {
            if($compression) gzwrite($zp, $return);
            else fwrite($handle,$return);
            }
        $return = "";
        }
    $count = 0;
    while($row = $result->fetch(PDO::FETCH_NUM)) {
        if($format <> "csv") $return = "\n\t(";
        for($j=0; $j < $num_fields; $j++) {
            //$row[$j] = preg_replace("\n","\\n",$row[$j]);
            if(isset($row[$j])) {
                if($format == "csv") $return .= '"'.$row[$j].'"';
                else {
                    //if number, take away "". else leave as string
                    if((in_array($type[$table][$j],$numtypes)) && (!empty($row[$j])))
                        $return .= $row[$j];
                    else
                        $return .= $DBH->quote($row[$j]);
                    }
                }
            else {
                if($format == "csv") $return .= '';
                else $return .= 'NULL';
                }
            if($j < ($num_fields-1)) $return .= ',';
            }
        $count++;
        if($format == "csv") $return .= "\n";
        else {
            if($count < ($result->rowCount()))
                $return .= "),";
            else $return .= ");";
            }
        if($format == "csv") fwrite($handle,$return);
        else {
            if($compression) gzwrite($zp, $return);
            else fwrite($handle,$return);
            }
        $return = "";
        }
    $return = "\n\n-- ------------------------------------------------ \n\n";
    echo " (".$count." records)";

    if($format <> "csv") {
        if($compression) gzwrite($zp, $return);
        else fwrite($handle,$return);
        }
    $return = "";

    $error1 = $pstm2->errorInfo();
    $error2 = $pstm3->errorInfo();
    $error3 = $result->errorInfo();
    echo $error1[2];
    echo $error2[2];
    echo $error3[2];

    if($format == "csv") fclose($handle);
    else {
        if($compression) gzclose($zp);
        else fclose($handle);
        }
    $filesize = filesize($filename);
    echo " - ".$filesize." bytes</small></li>";
    }
echo "</ul>";
chdir($olddir);
return;
}
于 2017-07-12T23:44:03.420 回答