这个坑值得记一笔。站点数据库里有四万篇文章,生成的 sitemap 只列了三万七千条,差的正好是最后几页,把 offset 命令手工跑一遍,超过两万之后返回的是空结果。

刚开始盯着「PHP 的 memory_limit 在拼接大数组时被撑爆,后半段直接中断」,折腾了半个多小时,排掉了。

这类报错背后常见的原因有几处,逐个排除就行。生成脚本按 offset 翻页,深层分页让数据库扫描代价指数上升;查询没有排序字段,翻页时行位置漂移导致漏掉部分记录;生成过程中有新文章写入,游标位置发生偏移。

先用 count 核对总数

SELECT COUNT(*) FROM wp_posts WHERE post_status='publish' AND post_type='post';

随后确认深层 offset 是否还能取到数据

SELECT ID FROM wp_posts WHERE post_status='publish' ORDER BY ID LIMIT 100 OFFSET 38000;

再往下改成按主键游标翻页

SELECT ID FROM wp_posts WHERE post_status='publish' AND ID > 37000 ORDER BY ID LIMIT 500;

末了核对生成前后的条数

grep -c '<loc>' sitemap-posts.xml

怎么算真的好了,看的是同一批现象。新生成的 sitemap 条数与数据库完全一致,最后几页的文章在提交后的第三天开始被抓取。

offset 翻页在数据量上万之后既慢又容易漏,换成按主键游标是这类问题的常规解法。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。

作者 9823189