← 返回首页

WordPress数据库迁移三大陷阱与修复

WordPress数据库迁移wp-cli

WP-CLI的search-replace命令会自动处理序列化数据的长度字段,这才是正确做法:

# 先dry-run看影响范围
wp search-replace 'old.example.com' 'new.example.com' --all-tables --dry-run --report-changed-only

# 确认无误后正式执行
wp search-replace 'old.example.com' 'new.example.com' --all-tables

两个关键参数不要省:

如果你的字段里有JSON(WordPress 5.7+的wp_usermeta部分字段已改用JSON),加上--precise

wp search-replace 'old.example.com' 'new.example.com' --all-tables --precise

--precise用PHP的preg_replace逐行处理而非MySQL的REPLACE(),速度慢3-5倍但对序列化和JSON数据更安全。

Collation不兼容:从MySQL 5.7搬到8.0的隐形炸弹

MySQL 8.0的默认collation从utf8mb4_unicode_ci变成了utf8mb4_0900_ai_ci。当你把5.7的数据库导入8.0时,SQL dump里的COLLATE=utf8mb4_unicode_ci和8.0默认的utf8mb4_0900_ai_ci混合,JOIN查询会直接报错:

Illegal mix of collations (utf8mb4_0900_ai_ci,IMPLICIT) and (utf8mb4_unicode_ci,IMPLICIT) for operation '='

这个错误安静地藏在后台,前台表现就是某些页面加载失败、WooCommerce订单查询报错、搜索功能失效。

修复方法:导入前统一collation,不是导入后修——导入后修要逐表逐列跑ALTER,几十张表改下来容易漏。

# 导出时把dump文件里的collation统一替换
mysqldump -u root -p wordpress_db > dump.sql
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' dump.sql
# 或者反过来,统一到0900
# sed -i 's/utf8mb4_unicode_ci/utf8mb4_0900_ai_ci/g' dump.sql

选哪个方向?**跟着目标服务器的MySQL版本走**。目标跑8.0就统一到utf8mb4_0900_ai_ci,目标跑5.7就统一到utf8mb4_unicode_ci

如果已经导入了、正在报错,批量修表:

# 生成所有需要修改的ALTER语句
mysql -u root -p -e "
SELECT CONCAT('ALTER TABLE \`', TABLE_NAME, '\` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'wordpress_db'
AND TABLE_COLLATION != 'utf8mb4_unicode_ci';" > fix_collation.sql

# 执行
mysql -u root -p wordpress_db < fix_collation.sql

WP-CLI search-replace的三个隐蔽遗漏

遗漏一:漏掉自定义表前缀的表

如果你的wp-config.php$table_prefix不是默认的wp_(比如wp_42_),wp search-replace的默认行为只处理注册到$wpdb的表。第三方插件自建的表不会自动包含。

# 错误:只替换默认注册的表
wp search-replace 'old.example.com' 'new.example.com'

# 正确:覆盖所有表
wp search-replace 'old.example.com' 'new.example.com' --all-tables

# 多站点情况
wp search-replace 'old.example.com' 'new.example.com' --network --all-tables

遗漏二:GUID字段不该替换

wp_posts表的guid列存的是文章的唯一标识,WordPress官方文档明确说guid在发布后不应更改。替换guid会导致RSS阅读器重新推送所有旧文章给订阅者。

# 排除guid列
wp search-replace 'old.example.com' 'new.example.com' --all-tables --skip-columns=guid

遗漏三:大站内存溢出

数据库超过1GB时,wp search-replace可能因为PHP内存限制中断。正确做法是分批处理:

# 按表逐一处理,避免全库扫描OOM
wp search-replace 'old.example.com' 'new.example.com' wp_options --dry-run
wp search-replace 'old.example.com' 'new.example.com' wp_postmeta --dry-run
wp search-replace 'old.example.com' 'new.example.com' wp_posts --dry-run
# 每张表确认后再去掉--dry-run正式执行

或者直接提高PHP内存限制:

wp search-replace 'old.example.com' 'new.example.com' --all-tables --skip-columns=guid --memory-limit=512M

迁移前后检查清单

迁移前:

1. 备份目标数据库(mysqldump全量备份)

2. 检查源和目标的MySQL版本、collation

3. wp search-replace --dry-run预估影响行数

迁移后:

# 1. 验证首页能访问
curl -sI https://new.example.com | head -5

# 2. 检查有无残余旧域名
wp db query "SELECT COUNT(*) FROM wp_options WHERE option_value LIKE '%old.example.com%'"

# 3. 刷新缓存和伪静态
wp cache flush
wp rewrite flush

# 4. 检查Collation混合
wp db query "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_COLLATION != 'utf8mb4_unicode_ci'" 2>/dev/null

如果你的WordPress站还有安全加固需求,可以参考我之前写的WordPress安全加固2026Cloudflare Tunnel零端口方案。数据库迁移本质上是运维操作,和网络安全、前端性能一样属于WordPress运维的必修课。

本文包含联盟链接。如果你通过链接购买,我可能获得佣金,不影响你的价格。

📌 本文由 AI 辅助生成并经人工审核发布 | TechPassive — AI 驱动的内容测试站点,专注于效率工具与 SaaS 真实评测

🔗 精选推荐工具

使用以下链接支持我们持续产出高质量内容(点击可直接前往购买):

☁️ DigitalOcean 云服务器 ⚡ Vultr 高性能 VPS 📚 WordPress Books 🔍 WordPress SEO Books 🌐 Web Hosting Books 🐳 Docker Books 🐧 Linux Books 🐍 Python Books 💰 Affiliate Marketing 💵 Passive Income Books 🖥️ Server Books ☁️ Cloud Computing Books 🚀 DevOps Books ⭐ MiniMax Token Plan 🔍 云盘搜索
← 返回首页