以下是对您提供的博文内容进行深度润色与工程化重构后的版本。我以一位深耕工业软件十余年、亲手在ARM工控机上跑过百万点/秒采集的老工程师视角,重新组织逻辑、强化实战细节、剔除AI腔调,并完全遵循您提出的全部格式与风格要求(无模块化标题、无总结段、自然收尾、语言真实有温度):
上位机历史数据怎么存?我在焊装线边缘设备上试了三年才敢说这话
去年冬天,我在某德系车企焊装车间调试一套新上位机系统。现场是台老款研华ARK-1550——Intel Atom x5-E3940,2GB DDR3,32GB eMMC。PLC用的是西门子S7-1500,通过OPC UA PubSub每50ms推送一次32轴机器人关节角度+200+IO状态。刚上线第三天凌晨,HMI历史曲线突然卡死,日志里反复刷着sqlite3_step() returned SQLITE_BUSY。重启后恢复,但第二天又来。最后发现,SQLite的WAL日志文件在eMMC上写满缓存区后,每次fsync要等800ms以上——而采集线程每50ms就往数据库塞一次数据,根本来不及消费。
这事儿让我彻底放下“数据库通用论”。上位机不是服务器,它是一台被钉在产线边柜里的嵌入式终端。它的内存不会因为你写了PRAGMA journal_mode = WAL;就多出1MB;它的SSD也不会因为你是PostgreSQL用户就给你开NVMe通道。真正决定你能不能把历史数据存下来的,从来不是文档里的TPS数字,而是top里那个持续飘红的%MEM,是iostat -x 1中await列跳动的毫秒数,是你在客户现场蹲着查dmesg | grep "mmc"时看到的那行mmcblk0: error -110。
所以今天不聊概念,只讲我在三类方案上踩过的坑、测出的数、改过的代码。
文件存储:不是“原始”,是“可控”
很多人一说文件存储,就觉得low。但我要说,在边缘侧,能精确控制每一字节落盘时机的方案,就是最硬核的高可用。
我们最早在一条包装线上用的就是纯BIN文件。结构极其简单:每条记录8+2+4=14字节(64位时间戳、16位tag索引、32位float值),按小时滚动,文件名带CRC校验和。没有索引文件,索引全靠内存映射+二分查找——因为磁盘IO比CPU贵十倍,宁可让RAM多占几MB,也不能让lseek()多跳一次。
关键不在“怎么存”,而在“怎么不死”。
比