針對雙主機 (A 動態 IP、B 固定 IP) MySQL 資料單向同步需求 (A→B),採用 PHP 腳本比對主鍵最大值增量同步,部署於 Crontab 定時執行,零成本實現基礎資料同步。
MAX(id),僅同步增量區間,避免全量覆蓋GRANT ALL ON `test`.* TO 'sync_user'@'%' IDENTIFIED BY 'StrongPass123!';
FLUSH PRIVILEGES;
-- 若報錯先用具體 IP,再用 phpMyAdmin 改為 %
'localhost', 'user'=>'user', 'pass'=>'pass', 'db'=>'test'];
$dst = ['host'=>'5.6.7.8', 'user'=>'sync_user', 'pass'=>'StrongPass123!', 'db'=>'test'];
$table = 'sync_table';
$pk = 'id';
// 連線函數
function connect($cfg) {
$link = mysqli_connect($cfg['host'], $cfg['user'], $cfg['pass'], $cfg['db']);
if (!$link) die("Connect failed: ".mysqli_connect_error());
mysqli_set_charset($link, 'utf8mb4');
return $link;
}
// 獲取最大主鍵
function getMaxId($link, $table, $pk) {
$res = mysqli_query($link, "SELECT MAX(`$pk`) AS max_id FROM `$table`");
$row = mysqli_fetch_assoc($res);
return $row['max_id'] ?? 0;
}
// 主流程
$srcLink = connect($src);
$srcMax = getMaxId($srcLink, $table, $pk);
mysqli_close($srcLink);
$dstLink = connect($dst);
$dstMax = getMaxId($dstLink, $table, $pk);
mysqli_close($dstLink);
if ($srcMax > $dstMax) {
$offset = $dstMax;
$limit = $srcMax - $dstMax;
$srcLink = connect($src);
$res = mysqli_query($srcLink, "SELECT * FROM `$table` WHERE `$pk` > $offset ORDER BY `$pk` LIMIT $limit");
$rows = [];
while ($row = mysqli_fetch_assoc($res)) $rows[] = $row;
mysqli_close($srcLink);
if ($rows) {
$dstLink = connect($dst);
// 批次 INSERT IGNORE (主鍵衝突忽略) 或 REPLACE INTO
$cols = array_keys($rows[0]);
$colList = '`'.implode('`,`', $cols).'`';
$placeholders = '('.implode(',', array_fill(0, count($cols), '?')).')';
$stmt = mysqli_prepare($dstLink, "INSERT IGNORE INTO `$table` ($colList) VALUES $placeholders");
// 綁定參數動態構建 (略,實際需 call_user_func_array)
foreach ($rows as $row) {
$vals = array_values($row);
// bind_param + execute ...
}
mysqli_stmt_close($stmt);
mysqli_close($dstLink);
echo "Synced ".count($rows)." rows.\n";
}
} else {
echo "No new data to sync.\n";
}
?>
UPDATE_TIME 或 BINLOG 同步。# 安裝 PHP CLI (通常已含)
which php # /usr/bin/php
# 測試腳本
php -q /home/httpd/html/sync.php
# -q 抑制 HTTP Header 輸出
# 編輯 crontab
crontab -e
# 每天 00:05 執行
5 0 * * * /usr/bin/php -q /home/httpd/html/sync.php >> /var/log/mysql_sync.log 2>&1
| 局限 | 演進方案 |
|---|---|
| 僅支援 INSERT 同步,不處理 UPDATE/DELETE | 讀取 Binlog (Canal/Maxwell/Debezium) 解析完整 DML 事件 |
| 主鍵非遞增或有刪除導致 MAX(id) 不準 | 基於 updated_at 時間戳增量、或 GTID 複制 |
| 大表全量初始化慢 | mysqldump --single-transaction --master-data=2 + 導入 |
| 無監控告警、無冪等保證 | 接入 Prometheus 監控同步延遲/行數、冪等寫入 (PK/UK) |
| 單點故障 (A 掛掉同步停) | 雙主互備 (MGR) 或從庫提升主庫 |
PHP + Crontab 方案適合「小數據量、單向、非核心、無運維資源」的臨時同步場景。核心業務務必上生產級 CDC/複制架構,確保資料一致性、可觀測性與故障自癒。