SHOW CREATE TABLE 獲取結構,SELECT * 獲取數據function table2sql($table) {
global $db;
$tabledump = "DROP TABLE IF EXISTS `$table`;\n";
$createtable = $db->query("SHOW CREATE TABLE `$table`");
$create = $db->fetch_row($createtable);
$tabledump .= $create[1] . ";\n\n";
return $tabledump;
}
function data2sql($table) {
global $db;
$tabledump = "DROP TABLE IF EXISTS `$table`;\n";
$createtable = $db->query("SHOW CREATE TABLE `$table`");
$create = $db->fetch_row($createtable);
$tabledump .= $create[1] . ";\n\n";
$rows = $db->query("SELECT * FROM `$table`");
$numfields = $db->num_fields($rows);
$numrows = $db->num_rows($rows);
while ($row = $db->fetch_row($rows)) {
$comma = "";
$tabledump .= "INSERT INTO `$table` VALUES(";
for ($i = 0; $i < $numfields; $i++) {
$tabledump .= $comma . "'" . mysql_escape_string($row[$i]) . "'";
$comma = ",";
}
$tabledump .= ");\n";
}
$tabledump .= "\n";
return $tabledump;
}
// 配置
$tables = ['us_sort', 'us_download', 'us_article', 'us_guestbook'];
$prefix = 'us_';
$saveto = 'server'; // 'local' 或 'server'
$back_mode = 'all'; // 'all' 結構+數據, 'table' 僅結構
$admin = 'heiyeluren';
$admin_email = 'heiyeluren@163.com';
// 執行備份
$sqldump = "";
foreach ($tables as $table) {
if ($back_mode == 'all') {
$sqldump .= data2sql($table);
}
if ($back_mode == 'table') {
$sqldump .= table2sql($table);
}
}
// 添加元數據頭
if (trim($sqldump)) {
$sqldump =
"# --------------------------------------------------------\n" .
"# 數據表備份\n" .
"#\n" .
"# 服務器: $db->Host\n" .
"# 數據庫:$db->Database\n" .
"# 備份編號: " . create_sess_id() . "\n" .
"# 備份時間: " . time_to_date('',6) . "\n" .
"#\n" .
"# 管理員:$admin ($admin_email)\n" .
"# $copyright\n" .
"# --------------------------------------------------------\n\n\n" .
$sqldump;
}
if ($saveto == "local") {
ob_end_clean();
header('Content-Encoding: none');
$ua = $_SERVER['HTTP_USER_AGENT'];
$ctype = (strpos($ua, 'MSIE') ? 'application/octetstream' : 'application/octet-stream');
header("Content-Type: $ctype");
$disposition = (strpos($ua, 'MSIE') ? 'inline; ' : 'attachment; ');
header("Content-Disposition: {$disposition}filename=\"$local_filename\"");
header('Content-Length: ' . strlen($sqldump));
header('Pragma: no-cache');
header('Expires: 0');
echo $sqldump;
exit;
}
if ($saveto == "server") {
if ($filename != "") {
@$fp = fopen($filename, "w+");
if ($fp) {
@flock($fp, LOCK_EX); // 3 = LOCK_EX
if (@!fwrite($fp, $sqldump)) {
@fclose($fp);
exit_msg("數據文件無法保存,請檢查目錄權限。");
} else {
exit_msg("數據成功備份至服務器 $filename 中。");
}
} else {
exit_msg("無法打開目錄 $filename,請確認存在且有寫權限。");
}
} else {
exit_msg("未輸入備份文件名。");
}
}
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
$stmt = $pdo->query("SHOW CREATE TABLE `$table`");
$create = $stmt->fetch(PDO::FETCH_NUM);
$tabledump = "DROP TABLE IF EXISTS `$table`;\n$create[1];\n\n";
$rows = $pdo->query("SELECT * FROM `$table`");
while ($row = $rows->fetch(PDO::FETCH_NUM)) {
$vals = array_map(function($v) use ($pdo) {
return "'" . $pdo->quote($v) . "'";
}, $row);
$tabledump .= "INSERT INTO `$table` VALUES(" . implode(",", $vals) . ");\n";
}
$offset = 0; $limit = 1000;
while (true) {
$rows = $pdo->query("SELECT * FROM `$table` LIMIT $offset, $limit");
$data = $rows->fetchAll(PDO::FETCH_NUM);
if (empty($data)) break;
// 處理 $data...
$offset += $limit;
}
if ($saveto == 'server') {
$gz = gzopen($filename . '.gz', 'wb9');
gzwrite($gz, $sqldump);
gzclose($gz);
} else {
header('Content-Encoding: gzip');
echo gzencode($sqldump, 9);
}
CREATE USER 'backup'@'localhost' IDENTIFIED BY 'strong_pass';
GRANT SELECT, LOCK TABLES, SHOW VIEW, EVENT, TRIGGER ON `db`.* TO 'backup'@'localhost';
FLUSH PRIVILEGES;
// 推送到 Redis/RabbitMQ 隊列
$job = ['tables' => $tables, 'mode' => $back_mode, 'target' => $saveto];
$redis->lpush('mysql_backup_queue', json_encode($job));
// Worker 進程消費
while (true) {
$job = json_decode($redis->rpop('mysql_backup_queue'), true);
if ($job) execute_backup($job);
}
# crontab -e
# 每天凌晨 2 點全量備份
0 2 * * * /usr/bin/php /path/to/backup.php --mode=all --target=server >> /var/log/mysql_backup.log 2>&1
# 每小時增量 (需 binlog 配合)
0 * * * * /usr/bin/php /path/to/backup.php --mode=incremental --target=server
這套 PHP 備份系統雖基於舊版 API,但架構清晰、功能完整。現代化改造後 (PDO、分批、壓縮、隊列、權限隔離),可直接投入生產作為輕量級備份補充方案。**核心原則:備份自動化、驗證常態化、恢復演練化**。