資料庫備份是維運核心任務。本文提供兩種 PHP 實作備份方案:單一檔案直輸出法適合簡單專案,函式封裝法支援指定資料表、彈性擴展,並說明現代化改進建議。
<?php
$host = "localhost";
$user = "root";
$password = "";
$dbname = "dbname";
$conn = mysql_connect($host, $user, $password);
mysql_select_db($dbname, $conn);
mysql_query("SET NAMES utf8", $conn);
$sql = "SET NAMES utf8;\n";
$tables = mysql_query("SHOW TABLES");
while ($t = mysql_fetch_array($tables)) {
$table = $t[0];
// 取得建表語句
$create = mysql_query("SHOW CREATE TABLE `$table`");
$row = mysql_fetch_array($create);
$sql .= $row['Create Table'] . ";\n\n";
// 取得資料
$data = mysql_query("SELECT * FROM `$table`");
while ($row = mysql_fetch_assoc($data)) {
$keys = array_map('addslashes', array_keys($row));
$vals = array_map('addslashes', array_values($row));
$sql .= "INSERT INTO `$table` (`" . implode('`,`', $keys) . "`) VALUES ('" . implode("','", $vals) . "');\n";
}
$sql .= "\n";
}
$filename = $dbname . date('Ymd') . ".sql";
file_put_contents($filename, $sql);
echo "備份成功:$filename";
?>
<?php
function backup_tables($host, $user, $pass, $name, $tables = '*') {
$link = mysql_connect($host, $user, $pass);
mysql_select_db($name, $link);
// 取得目標資料表
if ($tables == '*') {
$tables = [];
$result = mysql_query('SHOW TABLES');
while ($row = mysql_fetch_row($result)) $tables[] = $row[0];
} else {
$tables = is_array($tables) ? $tables : explode(',', $tables);
}
$return = '';
foreach ($tables as $table) {
$result = mysql_query("SELECT * FROM `$table`");
$fields = mysql_num_fields($result);
$return .= "DROP TABLE IF EXISTS `$table`;\n";
$row2 = mysql_fetch_row(mysql_query("SHOW CREATE TABLE `$table`"));
$return .= "\n\n" . $row2[1] . ";\n\n";
while ($row = mysql_fetch_row($result)) {
$return .= "INSERT INTO `$table` VALUES(";
for ($j = 0; $j < $fields; $j++) {
$row[$j] = addslashes($row[$j]);
$row[$j] = str_replace("\n", "\\n", $row[$j]);
$return .= isset($row[$j]) ? '"' . $row[$j] . '"' : '""';
if ($j < $fields - 1) $return .= ',';
}
$return .= ");\n";
}
$return .= "\n\n\n";
}
$filename = 'db-backup-' . time() . '-' . md5(implode(',', $tables)) . '.sql';
file_put_contents($filename, $return);
return $filename;
}
// 使用範例
backup_tables('localhost', 'root', '', 'dbname'); // 全庫備份
backup_tables('localhost', 'root', '', 'dbname', 'users,orders'); // 指定表
?>
mysql_* 函式已棄用(PHP 7.0+ 移除),生產環境請改用 mysqli 或 PDOaddslashes() 不足以防 SQL 注入,備份還原時需用參數化查詢mysqldump 系統指令或分批處理// 推薦:使用 mysqldump 系統指令(效能最佳、支援大數據)
$cmd = "mysqldump -h$host -u$user -p$pass $dbname --single-transaction --quick --lock-tables=false > $backupFile";
exec($cmd, $output, $returnVar);
// 或使用 PHP 進程控制避免阻塞
$proc = proc_open($cmd, [
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'] // stderr
], $pipes);
Linux/Cron 範例(每天凌晨 3 點):
0 3 * * * /usr/bin/php /path/to/backup.php >> /var/log/db_backup.log 2>&1