【结论】思路是对的,但补一句:**非 WordPress 的 CMS 别自己手写脚本遍历表,直接把 interconnect/it 的 Search-Replace-DB 单文件脚本丢到站点根目录跑一遍**。它内部就是逐条 unserialize → 替换 → 重新 serialize,对所有表通用,跑完记得把文件删掉。
如果连脚本都不想传,还有个纯文本层的办法:把库 dump 成 SQL 文件,用 Python 正则在文件里做替换,匹配 s:(\d+):"([^"]*)",替换内容后重新计算字节长度再拼回去。这样整库换完直接导入,不依赖任何 CMS,Discuz、DedeCMS、帝国这类没有 WP-CLI 的场景最省事。注意 PHP 序列化里的长度是字节数不是字符数,中文站点要用 len(s.encode('utf-8'))。
两个容易漏的点:
一是边界问题。wp search-replace 'old.com' 'new.com' 会把 old.com.cn、notold.com 一起命中,--precise 只保证不误伤序列化,不保证不误伤子串。保险写法是把模式带上协议或斜杠,比如 '//old.com',正式跑之前用 --report-changed-only --dry-run 把受影响的表和行数看一遍。
二是配置层和缓存层。wp-config.php 里如果硬编码了 WP_HOME / WP_SITEURL,数据库改了也白改,会覆盖回去;Discuz 在 config/config_global.php、帝国在 e/config/config.php 里也各有一份域名配置。改完必须清 Redis / Memcached 的 object cache、Discuz 的 data/cache、opcache 和 CDN,不然前台看到的还是旧域名,很多人以为没改成功又跑了一遍。
最后提一句你帖子里的 guid,那条非常关键——多站点的话 wp_site 和 wp_blogs 的 domain 列也是必改项,--all-tables 能覆盖到,但 wp-config.php 里的 DOMAIN_CURRENT_SITE 得手动同步。改完拿迁移前 grep -c 的数字对一遍,再进后台把插件列表点开确认没有“配置丢失”的提示,就算收工了。