⭐ 推荐:社区规则条款 V1.0

如何迁移WordPress数据库并保持链接不变?

GJ论坛站长
GJ论坛站长 管理员资深会员 👑黑卡会员
发布于 2026-10-24 15:38 ·6 浏览 ·3 回复
内容摘要

迁移WordPress数据库保持链接不变,域名不变时只需换服务器并核对站点URL;换域名须用WP-CLI等支持serialize的工具替换且跳过guid,迁移前备份数据库、wp-content和wp-config.php,测试后再切DNS。

迁移 WordPress 数据库并保持链接不变,核心只有一句话:**要么让域名保持不变(只换服务器),要么用能处理 serialize 序列化数据的方式做全文替换,并且永远不要手工修改 WordPress 的 guid 字段**。前者链接几乎不会改变;后者的常见问题是只用 SQL 直接替换,导致小工具、主题选项、页面构建器数据全部损坏。

迁移前必须备份哪些东西?

结论:一次完整的 WordPress 迁移要备份三样东西——数据库、wp-content 目录、wp-config.php,缺一不可。

导出数据库时建议用 mysqldump,并带上事务和字符集参数,避免大表锁死或中文乱码:

mysqldump -u dbuser -p --single-transaction --quick \
  --default-character-set=utf8mb4 wp_db > wp_db.sql

wp-content 用 rsync -avz wp-content/ user@新IP:/var/www/html/wp-content/ 传输,比打包下载再上传稳。备份完成后再操作,因为替换域名是不可逆动作,出错只能回滚。

域名不变、只换服务器,链接怎么保持?

结论:域名不变的情况下,链接天然不变,你只需要保证新服务器上的 wp-config.php 连对数据库、站点 URL 与旧站完全一致。

步骤是:新服务器装好 PHP + MySQL + Nginx,导入 wp_db.sql,拷贝整站文件和 wp-config.php,把里面的 DB_NAME、DB_USER、DB_PASSWORD、DB_HOST 改成新库的。接下来不要急着改 DNS,先本地改 hosts 指向新 IP 测试:

  • Linux/macOS:/etc/hosts
  • Windows:C:\Windows\System32\drivers\etc\hosts

加一行 新服务器IP www.你的域名.com,浏览器访问验证首页、内页、后台、图片、表单全部正常。验证通过后再把 DNS 的 A 记录切到新 IP。切换前 24 小时把域名 TTL 从 3600 秒调低到 300 秒,可以让生效时间从 1 小时缩到 5 分钟。

域名也换了,数据库怎么改才不出错?

结论:换域名必须用支持 serialize 序列化数据的替换工具,不能直接 UPDATE wp_options SET option_value = REPLACE(...)。

原因是 WordPress 把主题选项、小工具、页面构建器配置以 PHP serialize 格式存进数据库,格式形如 s:11:"http://old";,其中 11 是字符串长度。直接替换后长度对不上,反序列化会失败,表现为小工具全部消失、页面排版错乱。

推荐两种方式:

  1. WP-CLI(首选),需 WP-CLI 2.7 以上:
wp search-replace 'https://old.com' 'https://new.com' \
  --all-tables --precise --recurse-objects \
  --skip-columns=guid --dry-run

先跑 --dry-run 看会被改动的行数,确认无误后去掉 --dry-run 正式执行。--skip-columns=guid 必须保留:guid 是文章的唯一标识,WordPress 官方明确建议迁移后保持不变,否则阅读器会把老文章当成新文章重复推送。

  1. 插件方式:Better Search Replace 或 WP Migrate,界面里勾选所有表、勾选 “Run as dry run” 先预演,原理同样是序列化安全替换。

替换用的新旧域名不要带结尾斜杠,http 和 https 要分开各跑一次。

迁移完成后必须检查哪几项?

结论:迁移完成后,先做固定链接重写刷新,再检查 home 和 siteurl,最后处理混合内容。

按顺序过一遍:

  1. 后台「设置 → 固定链接」,什么都不改直接点保存,刷新 rewrite 规则并重写 .htaccess;只改域名后内页全部 404,大多是因为漏了这一步。
  2. 查 wp_options 表里 home 与 siteurl 两个值,必须都是新域名,且协议(http/https)一致。
  3. 在 wp-config.php 中可加 define('WP_HOME','https://new.com'); 和 define('WP_SITEURL','https://new.com'); 双保险,代价是后台这两项变灰不可编辑。
  4. 清缓存:插件缓存、CDN 缓存、浏览器缓存三层都要清,否则看到的是旧域名页面。
  5. 全站搜 http:// 混合内容,用浏览器 F12 控制台看有没有 Mixed Content 警告,图片裂开基本是这个原因。

迁移后图片和小工具丢了怎么办?

结论:图片裂开通常是 uploads 目录没同步完整,或数据库里存的是旧域名绝对路径;小工具丢失则几乎都是序列化被破坏。

先用 du -sh wp-content/uploads 对比新旧两侧体积,数字不一致就重传。路径问题用上面同一条 wp search-replace 再跑一次旧域名,注意 .sql 导出文件本身也可以替换,但必须用序列化安全工具处理后再导入。

如果小工具确实已损坏,只能从迁移前的备份里恢复那几张表(wp_options、wp_postmeta),重新用正确方式替换一次——这也是为什么第一步的备份不能省。

总结:保持链接不变的本质是“数据里的域名”和“解析指向的域名”始终一致。域名不变就靠 hosts 预演 + TTL 调低平滑切换;域名变了就靠 WP-CLI 的序列化安全替换,跳过 guid、先 dry-run、后刷新固定链接。整套流程照着做,内页 404、图片裂图、小工具消失这三类高发问题都能避开。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2502.html
转载请注明出处,版权归原作者所有。
他们都看过 1 人浏览过
GJ论坛站长
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 3

阿乐
阿乐 资深会员 1楼 2026-10-24 15:50

你这套流程框架是对的,但命令写断了,而且 --precise --recurse-objects 这几个参数只有 WP-CLI 2.7 以上才有;如果用的是 2.6 或更旧的版本,就需要先升级。完整命令补全如下:

# 第一步,只预览
wp search-replace 'https://old.com' 'https://new.com' \
  --all-tables --precise --recurse-objects \
  --skip-columns=guid --dry-run --report-changed-only

# 第二步,确认行数无误后去掉 --dry-run 正式执行
# 第三步,再跑一次 --dry-run,结果应为 0 行

几个容易出错的地方:域名变体一定要全部覆盖,http://old.com、https://old.com、old.com、带 www 和不带 www 的写法,数据库里四种都可能存在。建议按“完整协议域名 → 裸域名”的顺序分别执行;尤其是裸域名那一条,会命中用户邮箱和正文里的普通文字,因此务必先 dry-run 看命中的是哪张表。guid 字段不要修改,因为它只是 RSS 里的文章唯一标识,改了反而会让老订阅者收到重复内容。如果只想让 feed 里的链接显示正常,用 the_permalink_rss 过滤器修改即可,不必改动数据库。

如果替换完网址后进不了后台,先在 wp-config.php 里临时加入 define('WP_HOME','https://new.com'); 和 define('WP_SITEURL','https://new.com'); 救急;登录后再到设置里确认这两项,最后把这两行删掉,否则以后就无法在后台修改站点地址了。

还有一点顺带提醒:导入前先把新库建好,CREATE DATABASE wp_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;,否则导入后中文标题会变成一串问号,那时再回头修字符集非常麻烦。迁移完成并测试通过后,记得清理一遍对象缓存和 CDN,并给旧域名做 301 重定向,不要直接停解析。

lqyyzz
lqyyzz 观望站长 #2521 2楼 2026-10-24 16:07
阿乐:你这套流程框架是对的,但命令写断了,而且 `--precise --recurse-objects` 这几个参数只有 WP-CLI 2.7 以上才有;如果用的是…

你补的这几点都对,尤其 --dry-run --report-changed-only 和做完再跑一遍验证归零,这两步是整套流程里最该坚持的习惯。

再补两个我实际踩过的坑。第一,--all-tables 会扫整个数据库实例,如果新库上还挂着别的站或别的应用的表,会被一并替换掉,稳妥做法是换成 --all-tables-with-prefix,或者用 --include-columns 精确到具体的表和字段。第二,--precise 是逐行反序列化,几十万行 wp_postmeta 跑起来慢得离谱,表大的话建议按表分批执行,中途断了也好续,不至于从头再来。

关于裸域名那条,我一般放到最后单独跑,先 dry-run 看命中分布,重点确认 wp_posts.post_content 和 wp_users.user_email 有没有被误伤。邮箱被替换成新域名后用户收不到通知,这种问题往往过很久才暴露。另外字符集这块,除了建库时指定 utf8mb4,导出文件头也确认一下是 SET NAMES utf8mb4,老站可能是 utf8 甚至留着 latin1 残留,迁移前跑一次 wp db check 心里更有底。

替换完别忘了 wp cache flush 和 wp rewrite flush,伪静态规则不刷新的话内页会直接 404,很多人会误以为是替换把数据搞坏了。

chinaz
chinaz 初级会员萌新站长 #2533 3楼 2026-10-24 16:31
lqyyzz:你补的这几点都对,尤其 `--dry-run --report-changed-only` 和做完再跑一遍验证归零,这两步是整套流程里最该坚持的习惯。 再补两…

你补的这几条我基本都同意,尤其是把裸域名放到最后单独 dry-run 看命中分布,比任何参数都管用;我再加几个实际能省事的细节。

--all-tables-with-prefix 是按 $table_prefix 做匹配的,在共享库场景下最稳妥;但如果库里别的应用也用了同前缀(都叫 wp_ 的情况很常见),照样会误伤,这种就直接 --tables=wp_posts,wp_postmeta,wp_options,wp_usermeta 显式列举,可控性更高。--precise 慢的问题,我一般拆成两步:先用不加 --precise 的 SQL 模式把全库粗跑一遍,速度很快,能覆盖绝大多数纯文本字段;再对 wp_options、wp_postmeta、wp_usermeta 这几张存 serialize 的表加 --precise 精修。顺序千万别反,先 precise 再粗跑等于白干。跑之前顺手把 wp_actionscheduler_logs、wp_woocommerce_sessions 这类纯日志表用 --skip-tables 跳掉,时间能省一半以上。

邮箱那条再加一层保险:--skip-columns=guid,user_email 可以直接把用户邮箱列排除掉,绝大多数站点的邮箱跟站点域名本来就无关,没必要跟着换,跑前先 dry-run 确认这个列名被正确识别就行。

flush 再补两个经常漏的:对象缓存走 Redis 的话,wp cache flush 只清 WP 自己的缓存层,还得 wp redis flush 或后台清一次;用 Elementor 的记得 wp elementor flush-css,不然前端还是旧样式。wp rewrite flush 建议加 --hard,把 .htaccess 一并重写,比软刷新彻底,内页 404 基本就没了。