车间一跳闸,上位机里攒着没落盘的采集数据、写到一半的数据库事务、正在进行的配方下发,全都可能出问题。掉电保护不是"买个 UPS"就完事的,它是一套组合拳:硬件上争取缓冲时间、软件上优雅停机、数据上勤落盘勤备份、恢复上提前演练。这篇把我们交付项目里的完整方案拆开讲。

先盘点:断电瞬间到底会丢什么

内存里的在途数据

采集队列里还没写库的几百帧数据、未导出的报警记录,断电即蒸发。攒批入库的窗口期越长,丢得越多。

写一半的数据库事务

大批量 INSERT 进行到一半断电,轻则丢这一批,重则数据库文件损坏(SQLite 尤其敏感),开机连库都打不开。

进行中的控制动作

配方下发到一半、参数修改未确认,上电后上位机与 PLC 状态不一致,操作工不知道设备处于什么状态。

▲ 三类风险对应三套对策:在途数据靠"勤落盘 + 断电抢救",事务损坏靠"备份 + 日志模式",状态不一致靠"上电对账"。

第一道防线:UPS 不是摆设,要让程序"听得见"它

UPS 的价值不在"撑多久",而在把"突然死亡"变成"预告离场"。带 USB/串口通信的 UPS 可以上报市电状态,上位机监听到"市电丢失、电池供电"信号后,立刻走优雅停机流程:

触发市电丢失信号UPS 上报或 PLC 的市电监测位
停止新采集只出不进,队列开始排空
排空落盘队列余量全部批量写库,限时10秒
通知PLC写"上位机离线"标志位,设备转本地保持
关库退出正常关闭连接、写停机日志、退出进程

没有通信功能的廉价 UPS 也有土办法:让 PLC 监测市电接触器状态,断电瞬间给上位机写一个"市电丢失"的 M 点,上位机轮询到这个位就走同样的流程——反正断电时 PLC 和上位机通常同回路,谁先撑不住谁后走,能抢救几秒是几秒。整个流程必须控制在 UPS 电池时间的三分之一以内,留足余量。

第二道防线:平时就勤落盘,断电时损失才小

掉电保护的上限,取决于断电那一刻内存里有多少没落盘的数据。两个关键设置:

  • 攒批窗口别贪大:批量入库虽快,但 5 秒一批意味着最坏丢 5 秒数据。车间场景我们一般 1 秒或 100 条取先到者,追溯类数据(扫码、检验结果)逐条实时写,不进批
  • 关键状态写检查点:当前工单号、批次阶段、配方版本号这类"上电后要接着用"的状态,变化时立即写本地检查点文件(JSON 即可),上电先读检查点恢复上下文,而不是从零开始。
// 检查点:状态变化即写,原子替换防写坏
public void SaveCheckpoint(Checkpoint cp)
{
    var tmp = _path + ".tmp";
    File.WriteAllText(tmp, JsonSerializer.Serialize(cp));
    File.Move(tmp, _path, overwrite: true);
    // 先写临时文件再原子替换,断电最多丢一次变更,不会写坏旧文件
}

// 上电恢复:读检查点 + 与PLC对账
public void OnStartup()
{
    var cp = LoadCheckpoint();          // 可能为空(首次运行)
    var plcState = ReadPlcState();      // PLC侧的工单/批次状态
    if (cp != null && !cp.Match(plcState))
        RaiseMismatchAlarm(cp, plcState); // 不一致 → 报警让人确认,不自动猜
}
上电对账的原则:不一致时宁可报警停线等人确认,也不要自动"修复"。断电期间操作工可能手动动过设备,程序自作主张恢复状态,比丢数据更危险。

第三道防线:备份不是"备了"就行,要"能恢复"

数据库备份策略按库型分:

库型备份方式注意
SQLiteVACUUM INTO 每日全备 + 开启 WAL 模式直接复制 db 文件可能复制到写一半的状态,必须用 VACUUM INTO 或官方 Backup API;WAL 模式断电后自动回滚未提交事务,库不易坏
SQL Server每日全备 + 每小时日志备份恢复模式设为 FULL,日志备份保证最多丢一小时;生产库和上位机库分开实例
MySQLmysqldump 每日全备 + binloginnodb_flush_log_at_trx_commit=1 保证事务不丢

备份文件本身也要防"一锅端":本地留 7 天,每周拷一份到车间办公室的另一台机器或 NAS。备份和原库在同一块盘上,等于没备。

最重要的一条:备份必须做恢复演练。我们交付前固定动作——拿备份文件在一台干净的机器上真实恢复一次,确认数据完整、程序能连上。没演练过的备份,出事的概率接近五成:路径不对、版本不兼容、文件早就坏了,都是演练才能发现的。

收尾:掉电保护验收清单

  • 拉闸测试:断电后内存数据丢失量 ≤ 1 个攒批窗口;
  • UPS 信号触发后,程序在电池耗尽前完成优雅停机(有停机日志为证);
  • 断电瞬间正在写库,上电后数据库能正常打开、无损坏;
  • 上电后检查点恢复正确,状态不一致时能报警提示;
  • 备份文件在干净环境真实恢复成功一次(每季度重演)。

掉电保护这套东西,硬件花钱不多,软件逻辑也不复杂,真正值钱的是交付前那次真刀真枪的拉闸测试。如果你的项目从没测过断电场景,建议找个停产的晚上试一次——第一次测试发现的问题,绝对比客户现场发现的多。