WordPress 更换域名示意图:浏览器窗口下两个地球之间的迁移箭头,底部是数据库

WordPress 更换域名:可直接复制的 SQL 命令与序列化数据避坑指南

WordPress 换域名不只是改后台两个地址,旧域名散落在 options、posts、postmeta、comments 等多张表里。本文给出一套可直接复制的 SQL,讲清序列化数据为什么不能直接 REPLACE、如何用 WP-CLI 安全替换,以及 301 跳转和 Search Console 等收尾工作。

WordPress 换域名,表面上看只是在后台"设置 → 常规"里改两个地址,实际上旧域名散落在数据库的各个角落:文章内容里的图片链接、内链、自定义字段、主题和插件的设置、评论里的网址……只改后台那两项,前台很快就会出现图片打不开、链接跳回旧站、甚至后台登录不进去的问题。

这篇把我换域名时用的 SQL 整理成一套可以直接复制的命令,同时把最容易踩坑的"序列化数据"问题讲清楚,最后附上换完之后必须做的收尾工作。

第一步:先备份数据库

所有改数据库的操作之前,先备份,这一步没有商量余地:

mysqldump -u 用户名 -p --single-transaction --default-character-set=utf8mb4 数据库名 > backup-$(date +%F).sql

如果出了问题,用下面的命令恢复:

mysql -u 用户名 -p 数据库名 < backup-2026-10-17.sql

网站文件(尤其是 wp-content 目录和 wp-config.php)也建议一起打包备份。

第二步:确认表前缀

WordPress 默认表前缀是 wp_,但很多一键安装工具或出于安全考虑会改成别的,比如 wp8a3_。先查一下:

SHOW TABLES;

或者看 wp-config.php 里的 $table_prefix。下文所有 SQL 都按默认的 wp_ 写,你的前缀不同就整体替换掉。

另外,下面的示例里旧域名用 https://old.com,新域名用 https://new.com,执行前请替换成你自己的。建议带上协议一起替换,避免把无关的字符串误改。

我推荐的整体顺序

把下面的内容串起来,比较稳妥的顺序是:备份 → 确认前缀 → 新域名先完成解析和 SSL → 用 WP-CLI 或 SQL 替换数据库里的旧地址 → 清缓存、刷新固定链接 → 检查前台和后台 → 最后再给旧域名配置 301 跳转。

之所以把 301 放在最后,是因为一旦旧域名开始跳转,你就很难再回到旧站对照检查了。替换过程中如果发现问题,可以随时用备份恢复,再调整替换规则重新来一遍。整个过程建议选在访问量低的时段进行,并且在替换前暂停会写入数据库的定时任务和缓存预热,避免新旧数据混在一起。

第三步:核心 SQL 命令

1. 修改站点地址(wp_options)

这是最关键的两项,决定了 WordPress 认为自己"在哪个域名下":

UPDATE wp_options
SET option_value = REPLACE(option_value, 'https://old.com', 'https://new.com')
WHERE option_name IN ('home', 'siteurl');

执行后可以查一下确认:

SELECT option_name, option_value FROM wp_options WHERE option_name IN ('home', 'siteurl');

2. 修改文章和页面内容(wp_posts)

文章正文里的图片地址、内链都在 post_content 里:

UPDATE wp_posts
SET post_content = REPLACE(post_content, 'https://old.com', 'https://new.com');

文章摘要里如果也写了链接,可以顺带处理:

UPDATE wp_posts
SET post_excerpt = REPLACE(post_excerpt, 'https://old.com', 'https://new.com');

3. guid 字段(可选)

wp_posts 里还有一个 guid 字段,看起来是网址,其实是文章的全局唯一标识。WordPress 官方的建议是:已经公开发布、有 RSS 订阅的站点不要修改 guid,因为 RSS 阅读器靠它判断文章是不是新的,改了之后订阅者可能会收到一堆"新文章"。

但如果是整站迁移、开发环境搬到正式环境,或者附件(attachment)的 guid 被某些插件拿来当文件地址用,修改也问题不大。需要的话执行:

UPDATE wp_posts
SET guid = REPLACE(guid, 'https://old.com', 'https://new.com');

4. 自定义字段(wp_postmeta)

很多主题、页面构建器、SEO 插件会把链接存在文章的自定义字段里:

UPDATE wp_postmeta
SET meta_value = REPLACE(meta_value, 'https://old.com', 'https://new.com');

注意:这张表里有大量序列化数据,直接 REPLACE 有风险,后面会专门讲。

5. 评论(wp_comments)

评论者填写的网址和评论内容里的链接:

UPDATE wp_comments
SET comment_author_url = REPLACE(comment_author_url, 'https://old.com', 'https://new.com');

UPDATE wp_comments
SET comment_content = REPLACE(comment_content, 'https://old.com', 'https://new.com');

6. 用户资料(wp_usermeta,按需)

一般不用动,个别插件会把用户头像地址、个人主页等存在这里,搜索确认有旧域名再改:

SELECT umeta_id, meta_key FROM wp_usermeta WHERE meta_value LIKE '%old.com%';

UPDATE wp_usermeta
SET meta_value = REPLACE(meta_value, 'https://old.com', 'https://new.com');

7. 域名不变,只是 http 换成 https

如果只是给网站上了 SSL 证书,把上面所有语句里的旧值和新值换成:

UPDATE wp_posts
SET post_content = REPLACE(post_content, 'http://example.com', 'https://example.com');

其他表同理。别忘了带 www 和不带 www 的写法如果都出现过,要各替换一次。

8. 多站点(Multisite)

多站点网络涉及的表更多,简单列一下需要关注的地方:

  • wp_blogs:每个子站的 domain 字段。
  • wp_site:整个网络的 domain 字段。
  • wp_sitemeta:meta_key 为 siteurl 的记录。
  • wp_2_options、wp_3_options 等:每个子站各自的 home 和 siteurl,内容表也是 wp_2_posts、wp_2_postmeta 这样按站点编号分开的。
  • wp-config.php 里的 DOMAIN_CURRENT_SITE 常量也要同步修改。

例如:

UPDATE wp_blogs SET domain = REPLACE(domain, 'old.com', 'new.com');
UPDATE wp_site SET domain = REPLACE(domain, 'old.com', 'new.com');
UPDATE wp_sitemeta SET meta_value = REPLACE(meta_value, 'https://old.com', 'https://new.com') WHERE meta_key = 'siteurl';

多站点手写 SQL 很容易漏,更推荐用下面的 WP-CLI 加 --network 参数处理。

最大的坑:序列化数据

WordPress 和插件经常用 PHP 的 serialize() 把数组存进数据库,长这样:

a:1:{s:4:"logo";s:28:"https://old.com/img/logo.png";}

s:28 表示后面的字符串长度是 28。如果你用 SQL 的 REPLACE 把 old.com 换成了 newdomain.com,字符串变长了,但 s:28 没变,PHP 反序列化时就会失败,结果就是:主题设置丢失、小工具消失、插件配置恢复默认。

wp_options 和 wp_postmeta 是序列化数据的重灾区。只有新旧域名长度完全相同时,直接 REPLACE 才是安全的。

所以我的建议是:上面的 SQL 适合理解原理、处理 wp_options 的 home/siteurl 和 wp_posts 的正文这类纯文本字段;涉及 postmeta、options 等可能含序列化数据的表,交给能识别序列化的工具来做。

推荐方案:WP-CLI search-replace

服务器上能用 WP-CLI 的话,这是最省心的方案。它会自动识别序列化数据并修正长度:

# 先演练,看看会改哪些表、多少行,不实际写入
wp search-replace 'https://old.com' 'https://new.com' --all-tables --dry-run

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

# 跳过 guid 字段(如果你不想改它)
wp search-replace 'https://old.com' 'https://new.com' --all-tables --skip-columns=guid

# 多站点网络
wp search-replace 'https://old.com' 'https://new.com' --network

--all-tables 会连同插件建的非 WordPress 核心表一起处理。--precise 参数会强制所有替换都走 PHP 逐行处理,速度慢一些,但能处理一些复杂情况。

没有命令行时的替代方案

  • Better Search Replace 插件:后台操作,支持演练(dry run)和序列化数据,适合虚拟主机。
  • interconnect/it 的 Search Replace DB 脚本:上传到网站目录运行,同样支持序列化,用完一定要立刻删除,否则是严重的安全隐患。

另外,Elementor 等页面构建器会把数据以 JSON 形式存储,网址中的斜杠可能被转义成 https:\/\/old.com,普通替换匹配不到。Elementor 自带"替换 URL"工具,用它处理更稳妥。

应急方案:在 wp-config.php 里固定地址

如果改错了导致后台进不去,或者想先让新域名跑起来再慢慢替换,可以在 wp-config.php 里加上:

define( 'WP_HOME', 'https://new.com' );
define( 'WP_SITEURL', 'https://new.com' );

这会覆盖数据库里的 home 和 siteurl,后台对应的设置项也会变成灰色不可编辑。注意它只解决"站点地址"问题,文章里的旧链接还是需要上面的替换操作。

换完之后的收尾工作

数据库改完只完成了一半,剩下这些步骤同样重要:

1. 清理缓存

  • 清除缓存插件(WP Rocket、W3 Total Cache、LiteSpeed Cache 等)的缓存。
  • 有对象缓存(Redis / Memcached)的执行 wp cache flush。
  • 清除 CDN 缓存,并确认 CDN 回源配置已改成新域名。

2. 刷新固定链接

进入后台"设置 → 固定链接",什么都不用改,直接点一次保存,或者执行:

wp rewrite flush

3. DNS 和 SSL

  • 新域名解析到服务器,Nginx / Apache 的站点配置里加上新域名。
  • 为新域名申请 SSL 证书,确认 https 能正常访问。

4. 旧域名做 301 重定向

旧域名不要直接停掉,保留解析并做全站 301 跳转,把搜索引擎权重和老用户带到新域名。

Nginx:

server {
    listen 80;
    listen 443 ssl;
    server_name old.com www.old.com;

    ssl_certificate     /path/to/old.com/fullchain.pem;
    ssl_certificate_key /path/to/old.com/privkey.pem;

    return 301 https://new.com$request_uri;
}

Apache(旧域名站点根目录的 .htaccess):

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?old\.com$ [NC]
RewriteRule ^(.*)$ https://new.com/$1 [R=301,L]

注意旧域名的 https 访问也需要有效证书,否则用户在跳转前就会看到证书错误。

5. 通知搜索引擎

在 Google Search Console 中验证新域名,然后在旧域名资源的"设置"里使用"地址更改"(Change of Address)工具提交迁移,前提是 301 已经生效。同时提交新的 sitemap。Bing 网站管理员工具也有类似的站点迁移功能。

6. 最后检查

  • 前台随机打开几篇文章,看图片、内链是否正常。
  • 用浏览器开发者工具看有没有混合内容(Mixed Content)警告。
  • 在数据库里搜一下是否还有残留:wp db search 'old.com',或者导出 SQL 后用文本搜索。

总结

  1. 先用 mysqldump 备份数据库和网站文件。
  2. 用 SHOW TABLES 确认表前缀。
  3. 纯文本字段可以直接用 SQL REPLACE:wp_options 的 home/siteurl、wp_posts 的正文、wp_comments 等。
  4. guid 视情况决定是否修改,有 RSS 订阅的老站建议保留。
  5. 含序列化数据的表(options、postmeta)用 WP-CLI wp search-replace 或 Better Search Replace 处理,先 dry-run。
  6. 多站点注意 wp_blogs、wp_site、wp_sitemeta 和各子站的表,以及 DOMAIN_CURRENT_SITE。
  7. 收尾:清缓存和 CDN、刷新固定链接、配置 DNS 和 SSL、旧域名 301、Search Console 提交地址更改。

换域名不难,难的是不留死角。备份做好、先演练再执行,基本就不会出大问题。

暂无评论