You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

服务器关机重启时正在运行的SQL查询会继续执行还是停止

核心结论

未做特殊断点续跑设计的PHP数据处理脚本,遭遇服务停止、服务器关机重启时不会自动恢复执行;已经执行的SQL是否保留,完全由事务提交逻辑和数据库配置决定,不会出现半执行的脏数据。你本地测试停止Apache后任务终止的表现,和生产环境的运行逻辑完全一致。

不同中断场景的具体表现

场景1:仅重启Apache/PHP服务,数据库服务正常运行

你本地测试观察到的结果是符合底层运行逻辑的:PHP是依附于PHP工作进程(Apache mod_php模式下依附Apache进程,fpm模式下依附php-fpm进程)的解释型语言,进程被终止的瞬间,正在运行的脚本会直接退出,不会再向数据库发送后续的SQL请求。
这时候已经发送到数据库的操作遵循以下规则:

  • 如果数据库开启自动提交(MySQL InnoDB默认autocommit=1),已经执行完成、返回成功响应的update/delete/insert语句会直接持久化落盘,不会回滚
  • 如果你使用手动事务控制,还未执行COMMIT指令脚本就被终止,这一个事务内的所有操作会被数据库自动回滚,相当于从未执行过

场景2:服务器直接关机/重启,数据库进程被强制中断

这种场景下除了PHP脚本直接终止外,数据库下次启动时会自动执行崩溃恢复流程:

  • 所有已经完成提交的事务(含自动提交、手动commit的操作)会通过redo log完整恢复,不会丢失
  • 所有未完成提交的事务(含SQL发送一半、事务执行到一半就断电的操作)会通过undo log完整回滚,不会出现某条记录被改了一半的脏数据
    服务器重启完成后,不管是PHP还是数据库都不会自动续跑剩余的处理任务——没有任何组件会记录你的脚本总共要处理3000万条记录、当前已经跑到第几条。

为什么脚本不会自动续跑

PHP原生是无状态的单次请求执行模型,本身没有内置断点续跑、后台常驻执行的能力:

  • 你通过web请求触发的PHP脚本,生命周期完全和当前请求对应的工作进程绑定,进程退出后内存里存储的所有执行进度(比如已处理100万条、下一条要处理ID=1000001)会被完全清空
  • 数据库只负责处理接收到的单条SQL、单个事务,完全感知不到你上层PHP脚本的整体业务逻辑,自然不会帮你续跑剩下的任务

大批量数据处理的生产建议

  • 不要用单个事务包裹全部3000万条操作,一旦中断所有操作全部回滚,前面耗费的执行时间完全浪费,还会生成超大事务日志拖垮数据库性能。建议每处理1000~10000条记录就提交一次事务
  • 务必加断点标记:比如给待处理的表增加process_flag字段,处理完一条就把标记改为已处理,脚本每次启动先查询状态为未处理的记录再执行,哪怕中途服务器重启,重新触发脚本就能从上次中断的位置继续
  • 这类耗时几小时的长任务不要通过web请求触发,改用PHP CLI命令行模式执行,配合nohup或者systemd托管进程,避免web服务超时、进程重启自动杀掉任务
  • 正式跑全量数据前,先在测试环境模拟进程中断、服务器重启的场景,验证恢复逻辑符合预期,不要等任务跑了一半出问题才发现没做容错

内容的提问来源于stack exchange,提问作者cihan ranx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 09:15:34