本文约 3,493 字,预计阅读 9 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:拆分比启用难十倍
启用多站点是点几下鼠标的事,拆回去却是一项需要谨慎对待的手术。原因很简单:多站点的数据结构是”一套核心 + 全局表 + 按 ID 分表”,要拆出一个独立站点,等于要把这些分散的数据重新组装成一套完整的单站数据。
我见过有人在没备份的情况下直接删常量,结果整个网络打不开。第一步永远是备份。
原理分析:需要处理的四类数据
假设要把子站 ID=2(表前缀 wp_2_)拆成独立站点:
- 内容表:
wp_2_posts、wp_2_postmeta、wp_2_options、wp_2_terms、wp_2_term_taxonomy、wp_2_term_relationships、wp_2_comments、wp_2_commentmeta、wp_2_links; - 用户表:
wp_users、wp_usermeta是全网络共享的,需要按站点能力筛选; - 上传文件:
wp-content/uploads/sites/2/→wp-content/uploads/; - URL:子站可能是
mimangfei.com/shanghai或shanghai.mimangfei.com,拆分后要换成新域名。
其中用户表是最麻烦的:wp_usermeta 里的 wp_2_capabilities 决定用户在子站 2 的角色,独立后需要改名为 wp_capabilities。
保姆级实操
方案 A(推荐):导出内容重建(干净、风险低)
适用于内容量不大(几千篇文章以内)、不苛求保留用户 ID 的场景。
# 1. 在子站导出内容
wp --url=shanghai.mimangfei.com export --dir=/tmp/exp --post_type=post,page --status=publish
# 2. 拷贝上传文件
cp -a wp-content/uploads/sites/2/. /新站点/wp-content/uploads/
# 3. 在新站安装干净 WordPress
wp core download && wp config create ... && wp core install ...
# 4. 安装导入器并导入
wp plugin install wordpress-importer --activate
wp import /tmp/exp/*.xml --authors=create
# 5. 替换 URL
wp search-replace 'https://mimangfei.com/shanghai/wp-content/uploads' \
'https://newdomain.com/wp-content/uploads' --all-tables --precise --skip-columns=guid
优点:得到的是干净的独立站点,没有多站点残留表。缺点:用户、评论作者映射需要手工处理,设置不保留。
方案 B:数据库级拆分(保留全部数据)
# 0. 备份!
mysqldump -u root -p 数据库名 > before-split.sql
# 1. 导出子站内容表
mysqldump -u root -p 数据库名 \
wp_2_posts wp_2_postmeta wp_2_options wp_2_terms wp_2_term_taxonomy \
wp_2_term_relationships wp_2_comments wp_2_commentmeta wp_2_links \
> site2.sql
# 2. 改表名前缀
sed -i 's/`wp_2_/`wp_/g' site2.sql
处理用户表(关键步骤):
-- 创建新库后导入全量用户,再按子站能力筛选
-- 只保留在子站 2 有角色的用户
DELETE FROM wp_usermeta WHERE meta_key = 'wp_capabilities';
UPDATE wp_usermeta SET meta_key = 'wp_capabilities'
WHERE meta_key = 'wp_2_capabilities';
UPDATE wp_usermeta SET meta_key = 'wp_user_level'
WHERE meta_key = 'wp_2_user_level';
DELETE FROM wp_users
WHERE ID NOT IN (SELECT user_id FROM wp_usermeta WHERE meta_key = 'wp_capabilities');
修正 options 表:
UPDATE wp_options SET option_name = 'wp_user_roles'
WHERE option_name = 'wp_2_user_roles';
UPDATE wp_options SET option_value = REPLACE(option_value, 'wp-content/uploads/sites/2', 'wp-content/uploads')
WHERE option_value LIKE '%sites/2%';
移动上传文件:
mv wp-content/uploads/sites/2/* wp-content/uploads/
rmdir wp-content/uploads/sites/2
清理 wp-config.php:删除以下常量:
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', ...);
define('DOMAIN_CURRENT_SITE', ...);
define('PATH_CURRENT_SITE', ...);
define('SITE_ID_CURRENT_SITE', ...);
define('BLOG_ID_CURRENT_SITE', ...);
define('COOKIE_DOMAIN', ...);
define('WP_ALLOW_MULTISITE', true);
替换 URL 并刷新:
wp search-replace 'https://mimangfei.com/shanghai' 'https://newdomain.com' --all-tables --precise --skip-columns=guid
wp rewrite flush
wp cache flush
验证清单:
- 前后台可访问;
- 用户能登录且角色正确;
- 媒体库图片正常显示;
wp_user_roles存在(否则所有人权限异常);- 无
wp_blogs、wp_site、wp_sitemeta残留(可删)。
常见踩坑与失败案例
wp_user_roles没改名 —— 拆分后所有人无法登录,提示”您没有足够的权限”。这是最高频的失误。- 用户被清空 —— DELETE 语句写错条件,把有角色的用户也删了。执行前先
SELECT COUNT(*)验证条件。 - 案例:某站长拆分后前台正常,但后台所有插件菜单消失。原因是拆分时把
wp_2_options的wp_2_user_roles漏了,重建后恢复。 sed替换误伤 ——sed 's/wp_2_/wp_/g'会把正文里恰好出现的wp_2_字符串也改掉。建议只在表名上下文替换,或先检查 SQL 里是否有业务数据含该字符串。- 忘记清理
.htaccess—— 多站点的重写规则残留,导致新站路由异常。 - 拆分后 sitemap、SEO 设置丢失 ——
wp_2_options里部分插件设置依赖站点 ID,需要重新配置。
总结
拆分多站点的两条路:内容量小、追求干净 → 用导出导入(方案 A);数据必须完整保留 → 数据库级拆分(方案 B)。方案 B 里最容易出错的三处是 wp_user_roles 改名、用户筛选条件、uploads/sites/2 路径替换,做完这三步务必逐项验证。无论选哪条路,备份和先在测试库演练是不可跳过的——这项操作的回滚成本远高于准备成本。
