WordPress Multisite 实战踩坑 2026:从单站点迁移到多站网络的 5 个真实崩溃场景
最近帮一个外贸客户把 7 个独立 WordPress 站点合并到一套 Multisite 网络,原以为只是装个插件 + 改 wp-config.php 三分钟的事,结果第一周就撞了 5 次坑:从子站点白屏到 Cookie 串号,从 upload_path 把别人图片盖掉到 WP-CLI 命令默默失败。本文把这次真实排错过程全部还原,让你下次升级 Multisite 不用再走我走过的弯路。
🛠️ 前置准备
环境基线:
- WordPress 6.9.1(2026-02-03 维护版本;Multisite API 自 6.0 起无大改动,6.9 行为稳定)
- WP-CLI 2.11.x + PHP 8.2 + MySQL 8.0 / MariaDB 10.11
- 服务器:单 VPS,2GB+ RAM(每增加一个子站点预估 +20-50MB PHP 常驻)
- DNS:必须能配置 wildcard `*.example.com`(子域名模式)或纯 A 记录(子目录模式)
- 备份:整库 + uploads 目录
# 完整备份
wp db export /backup/full_$(date +%F).sql --allow-root
tar czf /backup/uploads_$(date +%F).tar.gz wp-content/uploads
第一步:启动 Multisite 前的检查清单
WordPress Multisite 不是开关按钮,是一个永久不可逆的架构决策——启用后回退到单站点会留下 wp_blogs / wp_signups 等孤立表。开工前必须确认:
1. **现有插件是否支持 Multisite**:wp plugin list --allow-root 检查每个插件是否注明 "Network: true"。常见不兼容:Yoast SEO 早期版本、W3 Total Cache、Jetpack 旧版
2. **uploads 目录清理**:单站点的 wp-content/uploads/2024/ 等历史目录必须迁完,启用 Multisite 后上传路径会变为 wp-content/uploads/sites/{blog_id}/
3. **数据库前缀一致性**:单站点通常 wp_,Multisite 表是 wp_blogs / wp_blog_versions / wp_registration_log / wp_signups / wp_site / wp_sitemeta —— 这些表**不会自动创建**,必须首次进入 Tools → Network Setup 后由 WP 写入
4. **WordPress 地址不可换域名**:一旦确定 example.com 是主站点,后续切换成本极高(涉及 wp_site / wp_blogs 全量替换)
第二步:启用 Multisite(最容易出错的两步)
在 wp-config.php 添加(**位置在 /* That's all... */ 注释前**):
define('WP_ALLOW_MULTISITE', true);
刷新后台,进入 Tools → Network Setup:
- **Subdomains**(推荐生产环境):子站点是 `site1.example.com`,需要 wildcard DNS + wildcard SSL
- **Subdirectories**(仅适合全新站):`example.com/site1/`,无需 DNS,但 SEO 不友好
填好后点击 Install,会给出两段代码:**第一段**添加到 wp-config.php:
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', true);
define('DOMAIN_CURRENT_SITE', 'example.com');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);
**第二段**添加到 .htaccess(Apache)或 Nginx 的 try_files 重写规则(推荐 Nginx)。如果忘了改 web server 配置,子站点全部 404。
💣 踩坑实录:5 个真实崩溃场景
坑 1:wordpress-mu-domain-mapping 插件 + SUNRISE 顺序错乱
**症状**:启用 Domain Mapping 插件后子站点全部白屏,PHP 报错 Use of undefined constant SUNRISE。
**根因**:插件要求 wp-config.php 里 define('SUNRISE', true);,但 WordPress 核心在 MU plugins 阶段才读取这个常量——如果你的 SUNRISE 写在 /* That's all, stop editing! */ 之后,可能在某些插件加载顺序下被忽略。
修复:
// wp-config.php 必须把 SUNRISE 放在 MU plugin 加载前(推荐位置:DB_COLLATE 之后)
define('SUNRISE', true);
define('DB_COLLATE', '');
define('AUTH_KEY', '...');
// ... 其他常量
// 再放置 WP_DEBUG 验证
define('WP_DEBUG', true);
define('WP_DEBUG_LOG', true);
预防:SUNRISE 永远写在 wp-config.php 顶部、ABSPATH 之前。
坑 2:Cookie 域名配置错误,所有子站点登录后立即失效
症状:登录子站点 A,刷新页面又跳回登录页;同一浏览器开子站点 B,看到 A 的后台。
**根因**:WordPress 默认 cookie domain 是 example.com,子域名 site1.example.com 应该共享——但如果 wp-config.php 里有遗留的 define('COOKIE_DOMAIN', 'www.example.com');,会让 cookie 跨子站失效。
修复:
// 删除 COOKIE_DOMAIN 显式定义(让 WP 自动用 DOMAIN_CURRENT_SITE)
// 或者正确写法
define('COOKIE_DOMAIN', $_SERVER['HTTP_HOST']);
define('COOKIEPATH', '/');
define('SITECOOKIEPATH', '/');
**预防**:迁移前 grep COOKIE wp-config.php,启用 Multisite 后必须删。
坑 3:upload_path 没改,子站点上传直接覆盖主站点图片
症状:在子站点上传图片,文件名重复,主站点那张图片被无声覆盖。
**根因**:Multisite 启用后,wp_options 里的 upload_path 默认继承主站点值,**第一次**新增子站点时必须让 WordPress 写新值,否则所有子站都写到 wp-content/uploads/。
修复(WP-CLI 一次性修复所有子站点):
# 主站点跳过
wp option update upload_path 'wp-content/uploads' --allow-root
# 子站点单独修复(blog_id 从 wp_blogs 表查)
wp --url=site1.example.com option update upload_path 'wp-content/uploads/sites/2' --allow-root
wp --url=site1.example.com option update upload_url_path 'https://site1.example.com/wp-content/uploads/sites/2' --allow-root
预防:每次新增子站点后立即跑上述三行。
坑 4:WP-CLI 默默失败,子站点配置改不进去
**症状**:运行 wp option update blogname '新名字' --url=site1.example.com --allow-root,返回 Success,但后台看子站点名字没变。
**根因**:WP-CLI 在 multisite 模式下需要 --url= 来切换上下文,但部分命令(如 wp post create)要求同时加 --network 或者直接走 wp site 子命令。
修复:
# 错误写法("成功"但无效)
wp option update blogname 'New Name' --allow-root
# 正确写法(指定子站 URL)
wp option update blogname 'New Name' --url=https://site1.example.com --allow-root
# 更稳:先用 wp site list 看 blog_id
wp site list --allow-root
# 然后用 --url= 单站定位
# 跨网络批量(必须带 --network)
wp post list --post_type=product --network --allow-root
**预防**:所有 WP-CLI 单子站点操作**永远**先加 --url=。
坑 5:Wildcard SSL 没配置,子站点 HTTPS 全挂
**症状**:主站 https://example.com 正常,所有 https://site1.example.com 浏览器报 NET::ERR_CERT_COMMON_NAME_INVALID。
**根因**:Let's Encrypt 单证书只覆盖 example.com + www.example.com,子域名需要 wildcard 证书 *.example.com。
修复(Certbot + Nginx):
# 一次性签发 wildcard(需要 DNS TXT 验证)
certbot certonly --manual --preferred-challenges=dns \
-d example.com -d "*.example.com"
# Nginx 配置(关键:ssl_certificate 必须指向 wildcard 证书)
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 自动续期(重要:续期必须重新加 DNS TXT 记录)
# 改用 acme-dns 或 certbot-dns-cloudflare 插件避免手动
**预防**:启用 Subdomain Multisite **前**先签 wildcard 证书;用 acme.sh + Cloudflare API 全自动续签最省事。
🛡️ 进阶:Multisite 性能与备份策略
启用 Multisite 后,每个子站点的 wp_posts / wp_postmeta 是**独立表**(不是分表!),但 wp_options 仍然**全网络共享一张表**(所以 wp_options autoload 问题会被放大)。
# 备份整网络(必须带 --network)
wp db export /backup/network_$(date +%F).sql --allow-root
# 还原单个子站点(精确恢复,不影响其他子站)
wp db export /backup/presite1.sql --allow-root
# 1. 找出子站点所有表(blog_id=2)
# 2. 仅 dump 这些表 + 共享 wp_users
进阶优化:
- **对象缓存必须共享**:Redis Object Cache 配 `WP_CACHE_KEY_SALT` 区分网络
- **媒体分离到 CDN**:用 WP Offload Media 插件,避免 uploads 拖垮单 VPS
- **wp-config.php 锁定站点 ID**:避免管理员误删主站点
总结与下一步
Multisite 是把"管理 7 个站点"的成本压缩到"管理 1 个核心"的好方案,但启用前的检查清单和启用后立刻要修的 5 个坑必须心里有数。下次给客户做迁移时,我会先跑一份「启用前 10 项检查 + 启用后 30 分钟必跑修复脚本」作为合同附件,把坑前置化。
如果你是第一次接触 Multisite,建议先用 localhost.wp + Subdirectory 模式练手,不要直接上 Subdomain + Wildcard SSL——前者不需要 DNS 改动,后者 5 个坑会全撞一遍。
相关阅读:WordPress 数据库迁移三大陷阱与修复(Multisite 迁移的预热)和 WordPress Nginx 配置完整踩坑指南(Multisite 的 web server 重写规则都需要)。
👉 Join MiniMax Token Plan: AI coding acceleration for businesses
👉 Join Zhipu Coding Plan: GLM-4.6/GLM-5 coding packages, China-stable, pay-per-token unlimited
👉 Join Aliyun AI: Top AI products with exclusive coupons for business innovation
📌 This article was AI-assisted generated and human-reviewed | TechPassive — An AI-driven content testing site focused on real tool reviews
🔗 Recommended Tools
These are carefully selected tools. Using our affiliate links supports us to keep producing quality content: