核心结论:CMS 迁移出问题,九成不是"安装"环节,而是环境不一致(PHP/MySQL 版本、扩展、排序规则)和域名硬编码在数据库里没做正确的搜索替换。按「对齐环境 → 打包文件 → 单事务导库 → 建库指定字符集 → 全站搜索替换 → 清缓存验证」这六步走,能把白屏、404、图片裂图这三类故障压到最低。
迁移前要先确认哪些环境差异?
结论:先逐项核对旧站与新站的 PHP 版本、数据库版本、Web 服务器类型和已装扩展,这四项任何一项不一致,都可能直接白屏。
具体做法是在两台机器上分别执行 php -v、mysql --version、php -m、nginx -v 或 httpd -v,把输出逐行比对。CMS 必需扩展至少覆盖 mysqli/pdo_mysql、gd 或 imagick、curl、mbstring、zip、fileinfo、intl、opcache。
三个高频坑要提前规避:一是 PHP 8 移除了 each()、create_function() 等函数,旧主题插件会直接报致命错误,建议新环境先装与旧站相同的 PHP 版本跑通,再单独升级;二是 MySQL 8 默认排序规则是 utf8mb4_0900_ai_ci,与旧站的 utf8mb4_general_ci 混用会在 JOIN 时报 "Illegal mix of collations";三是 MySQL 5.7 之后默认开启 ONLY_FULL_GROUP_BY 严格模式,旧插件里不合规的 GROUP BY 查询会直接失败。
文件和数据怎么搬才不出错?
结论:文件用 tar 整体打包(包含所有隐藏文件),数据库用 mysqldump 加 --single-transaction 导出,数据量超过 50MB 就不要用 phpMyAdmin。
打包命令:
tar -czf site.tar.gz -C /var/www/html .
mysqldump -u user -p --single-transaction --default-character-set=utf8mb4 \
--routines --triggers --events dbname | gzip > db.sql.gz
新手最常漏的是 .htaccess、.user.ini、.well-known、robots.txt 这些以点开头的文件,tar -C dir . 能全部带上,用 cp -r * 则会丢。解压后目录权限统一设为 755、文件 644,上传目录 uploads 若 CMS 需要写入才给 775,属主必须是 Web 运行用户(如 www-data),否则后台传图会报权限错误。
导入前先手动建库并锁定字符集,不要依赖默认值:
CREATE DATABASE dbname DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
大库导入加上 mysql --max_allowed_packet=64M,否则单条 INSERT 超过 16MB 会被截断。
域名换了,为什么后台进不去、图片全裂?
结论:因为 CMS 会把站点地址写进数据库(WordPress 存在 wp_options 的 siteurl、home 两行),不替换就会一直跳回旧域名,而且这些数据里含序列化字符串,直接 UPDATE 会破坏长度。
正确做法是用 CMS 自带工具替换:
wp search-replace 'old.com' 'new.com' --all-tables --precise
--precise 会重算 PHP 序列化字符串的字节长度,用 SQL 的 REPLACE() 直接跑会导致主题设置、小工具配置全部丢失并报 unserialize 错误。替换范围还要覆盖文章正文里的内链、CDN 静态域名、邮件模板、跳转规则。
测试阶段不想改 DNS,可以本地修改 hosts 文件把新域名指向新服务器 IP,先验证功能再动解析。
新环境配置有哪些必改项?
结论:配置文件里的数据库连接、缓存后端、伪静态规则、上传参数这四类必须逐条改,改完还要清所有层级的缓存。
- 配置文件:数据库主机/账号/密码,以及
WP_HOME、WP_SITEURL 这类常量。
- 伪静态:旧站若是 Apache
.htaccess,迁到 Nginx 必须改写成 try_files $uri $uri/ /index.php?$args;,否则除首页外全是 404。
- php.ini:
memory_limit 建议 256M,upload_max_filesize 与 post_max_size 至少 64M,max_execution_time 300。
- 缓存:opcache、Redis/Memcached 对象缓存、CMS 页面缓存、CDN、浏览器缓存,五层都要清,只清一层会看到"改了没生效"。
- 定时任务:把旧的 crontab 条目迁过来,路径若变了要同步改。
切换时怎么降低风险?
结论:提前 24-48 小时把 DNS TTL 从 3600 降到 300,停写窗口内做最后一次数据库增量同步,切换后旧服务器保留至少 7 天可回滚。
验证清单按顺序跑一遍:首页 200、登录后台、搜索、表单提交、伪静态文章页、404 页面、邮件能发出、缩略图能生成、定时任务执行日志。全部通过后再放开 TTL。
迁移不是一次性动作,而是一次"环境对齐 + 数据替换"的完整工程。把版本差异提前对齐、把字符集显式指定、把域名用带序列化处理的工具替换、把所有缓存层清干净,这四件事做到位,剩下的都是流程问题。