萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

PHP 匯出匯入大型 MySQL 資料庫實作:突破 phpMyAdmin 限制

為什麼需要 PHP 方案?

虛擬主機環境常限制 upload_max_filesize、post_max_size、max_execution_time,導致 phpMyAdmin 匯入大型 SQL 檔案失敗。自製 PHP 腳本可分批處理、繞過限制。

核心思路

  1. 匯出:將資料表內容寫入文字檔,欄位間用特殊分隔符(如 &&jimmy&&)區隔,避免資料本身含分隔符衝突
  2. 匯入:讀取文字檔,按分隔符解析重組 INSERT 語句執行

匯出程式碼(重構優化版)

<?php
// 設定
$host = 'localhost';
$user = 'root';
$pass = '';
$dbname = 'your_db';
$table = 'your_table';
$output = $table . '.txt';

$mysqli = new mysqli($host, $user, $pass, $dbname);
if ($mysqli->connect_errno) {
    die('Connect failed: ' . $mysqli->connect_error);
}

$mysqli->set_charset('utf8mb4');

$result = $mysqli->query("SELECT * FROM `$table`");
if (!$result || $result->num_rows === 0) {
    die('No data or error: ' . $mysqli->error);
}

$fp = fopen($output, 'w');
$fieldCount = $result->field_count;
fwrite($fp, $fieldCount . " "); // 寫入欄位數

$delimiter = '&&jimmy&&';

while ($row = $result->fetch_row()) {
    foreach ($row as $i => $val) {
        // 轉義分隔符與換行
        $val = str_replace($delimiter, $delimiter . $delimiter, $val);
        $val = str_replace("\n", '\n', $val);
        $val = str_replace("\r", '\r', $val);
        fwrite($fp, $val . " ");
    }
    fwrite($fp, "------- PHP MySQL Dump V1.0 -------- ");
}

fclose($fp);
$mysqli->close();
echo "Export done: $output";
?>

匯入程式碼(重構優化版)

<?php
$host = 'localhost';
$user = 'root';
$pass = '';
$dbname = 'your_db';
$table = 'your_table';
$input = $table . '.txt';

$mysqli = new mysqli($host, $user, $pass, $dbname);
if ($mysqli->connect_errno) die('Connect failed: ' . $mysqli->connect_error);
$mysqli->set_charset('utf8mb4');

$lines = file($input, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
if (!$lines) die('File empty');

$fieldCount = (int)trim(array_shift($lines));
$delimiter = '&&jimmy&&';
$batch = [];
$batchSize = 1000; // 批次提交

foreach ($lines as $line) {
    if (strpos($line, '------- PHP MySQL Dump') !== false) continue; // 跳過分隔行
    
    $parts = explode(' ', $line, $fieldCount);
    if (count($parts) !== $fieldCount) continue; // 格式錯誤跳過
    
    $values = [];
    foreach ($parts as $val) {
        $val = str_replace($delimiter . $delimiter, $delimiter, $val);
        $val = str_replace('\n', "\n", $val);
        $val = str_replace('\r', "\r", $val);
        $values[] = "'" . $mysqli->real_escape_string($val) . "'";
    }
    
    $batch[] = '(' . implode(',', $values) . ')';
    
    if (count($batch) >= $batchSize) {
        $sql = "INSERT INTO `$table` VALUES " . implode(',', $batch);
        if (!$mysqli->query($sql)) {
            error_log("Import error: " . $mysqli->error . " SQL: $sql");
        }
        $batch = [];
    }
}

// 餘數提交
if ($batch) {
    $sql = "INSERT INTO `$table` VALUES " . implode(',', $batch);
    $mysqli->query($sql);
}

$mysqli->close();
echo "Import completed.";
?>

關鍵改進點

  • 使用 mysqli 取代已棄用的 mysql 擴展
  • 採用 real_escape_string 防止 SQL 注入
  • 批次插入(batchSize)大幅提升匯入效能
  • 正確處理分隔符轉義與換行符
  • 錯誤記錄不中斷流程

進階建議

  • 超大資料庫建議配合 mysqldump --single-transaction --quick 熱備份
  • 考慮使用 LOAD DATA INFILE 替代 INSERT,速度快 10-20 倍
  • 生產環境務必加入權限驗證、CSRF 保護、日誌記錄
copyright © 萬盛學電腦網 all rights reserved