
WordPress 的 get_option() 在长时 AJAX 请求中会因对象缓存未更新而无法获取其他请求刚写入的新值,需手动清除缓存才能实时读取最新状态。
wordpress 的 `get_option()` 在长时 ajax 请求中会因对象缓存未更新而无法获取其他请求刚写入的新值,需手动清除缓存才能实时读取最新状态。
在 WordPress 开发中,实现可中断的批量处理任务(如数据导入、定时同步)是一个常见需求。典型做法是:前端发起一个长时间运行的 AJAX 请求(wp_ajax_batch),后端循环处理数据项,并在每次迭代中检查一个全局状态标志(如存储在 wp_options 表中的 batch_state);同时提供另一个 AJAX 接口(wp_ajax_cancel_batch)用于将该状态设为 'cancelled',从而通知主任务提前退出。
然而,开发者常遇到如下问题:尽管 cancel_batch 成功调用 update_option('batch_state', 'cancelled'),主任务循环内的 get_option('batch_state') 却始终返回旧值(如 'running'),导致无法及时响应取消指令。
根本原因在于 WordPress 的对象缓存机制:
get_option() 默认会先从内存缓存(wp_cache_get())读取值,仅当缓存未命中时才查询数据库。而 update_option() 虽然会更新数据库并刷新自身缓存,但不会自动通知或同步其他并发请求的缓存实例。由于每个 PHP 请求拥有独立的执行环境和内存空间(包括 WP_Object_Cache 实例),主批量请求的缓存不会感知到另一个请求对同一选项的修改——这正是“隔离环境”的体现。
✅ 正确解决方案:在循环内显式清理缓存
add_action('wp_ajax_batch', 'my_ajax_batch_handler');
function my_ajax_batch_handler() {
check_ajax_referer('batch_nonce', 'nonce');
update_option('batch_state', 'running');
// 示例数据(实际中应从数据库或外部源分批获取)
$values = range(1, 1000);
foreach ($values as $item) {
// 关键:强制刷新选项缓存,确保读取最新数据库值
wp_cache_delete('batch_state', 'options'); // 推荐:精准删除指定键
// 或使用更彻底的方式(慎用高并发场景):
// wp_cache_flush(); // 清空全部对象缓存(影响其他选项)
$batch_state = get_option('batch_state', 'running');
if ('cancelled' === $batch_state || 'stopping' === $batch_state) {
error_log("Batch cancelled at item: $item");
wp_send_json_success(['status' => 'cancelled', 'processed' => $item]);
return;
}
// 执行单条业务逻辑(注意控制耗时,避免超时)
process_single_item($item);
// 可选:每 N 次迭代做一次轻量级心跳或进度上报
if ($item % 50 === 0) {
wp_cache_flush(); // 避免缓存膨胀(非必需)
}
}
update_option('batch_state', 'completed');
wp_send_json_success(['status' => 'completed']);
}⚠️ 注意事项与最佳实践:
- 优先使用 wp_cache_delete( $key, $group ):$group 参数必须为 'options'(get_option() 默认使用的组),比 wp_cache_flush() 更精准、性能更优;
- 避免高频 wp_cache_flush():它会清空整个对象缓存,可能影响其他插件/主题的性能;
- 添加非阻塞校验与超时保护:长循环应配合 set_time_limit(0)(谨慎启用)、sleep(0.01) 或 usleep(10000) 防止 CPU 占满,并设置最大执行时间兜底;
- 增强健壮性:建议搭配 transient 或自定义数据库表存储状态,支持更丰富的字段(如 updated_at, cancellation_requested_by);
- 前端需配合轮询或 Server-Sent Events(SSE):单纯依赖取消请求无法保证主任务立即终止,应设计“软取消”+“状态轮询”双机制;
- 务必校验权限与 nonce:所有 AJAX 处理函数开头应调用 current_user_can() 和 check_ajax_referer(),防止未授权操作。
通过主动管理对象缓存生命周期,即可让多个并发 AJAX 请求之间实现可靠的共享状态通信——这是构建可中断、可观测、生产就绪型 WordPress 后台任务的关键一环。










