1200次Reboot测试触发BMC NandFlash写入量超限

问题背景

25.12LTS版本跑了1200次OS的Reboot测试(约5分半一圈),出现告警The data written to the NAND flash in last 15 days exceeds 12G


查看每天写入量达到4个多GB

openUBMC:/->mdbctl lsprop NandFlash_00 bmc.kepler.Managers.NandFlash
bmc.kepler.Managers.NandFlash
  EraseCountPerDays=[2,1,2,2,1,1]
  LifeTime=89
  LifeTimeThreshold=10
  MaxEraseCount=3000
  OverWrite=1
  PreEOL=1
  RWTestState=0
  RemainingEraseCount=2690
  ReservedBlocks=90
  RuntimeBadBlocks=0
  TotalWriteAmount=21.21
  TotalWriteAmountIn15Days=21.21
  Vendor="Hynix"
  WriteAmountPerDay=[4.52,4.506,4.57,4.34,2.961,0.314]
  WriteProtection=0
  WriteThreshold=12

初步分析

使用BMC NandFlash写入量过大问题的定位思路分享 - 交流互助区 - openUBMC 论坛的分析思路可以定位到主要是framework的数据库写入导致的

~ /opt/bmc/apps/hica # sqlite3  /data/trust/persistence/per_poweroff.db .dbinfo
database page size:  1024
write format:        1
read format:         1
reserved bytes:      0
file change counter: 120134
database page count: 779
freelist page count: 7
schema cookie:       4
schema format:       4
default cache size:  0
autovacuum top root: 0
incremental vacuum:  0
text encoding:       1 (utf8)
user version:        0
application id:      0
software version:    3042000
number of tables:    3
number of indexes:   3
number of triggers:  0
number of views:     0
schema size:         655
data version         2
~ /opt/bmc/apps/hica # sqlite3  /opt/bmc/pram/persistence.local/maca.db .dbinfo
database page size:  4096
write format:        1
read format:         1
reserved bytes:      0
file change counter: 507668
database page count: 7
freelist page count: 0
schema cookie:       3
schema format:       4
default cache size:  0
autovacuum top root: 0
incremental vacuum:  0
text encoding:       1 (utf8)
user version:        0
application id:      0
software version:    3042000
number of tables:    3
number of indexes:   3
number of triggers:  0
number of views:     0
schema size:         432
data version         1
~ /opt/bmc/apps/hica # sqlite3 /opt/bmc/pram/persistence/per_reset.db .dbinfo
database page size:  4096
write format:        1
read format:         1
reserved bytes:      0
file change counter: 37564
database page count: 76
freelist page count: 0
schema cookie:       2
schema format:       4
default cache size:  0
autovacuum top root: 0
incremental vacuum:  0
text encoding:       1 (utf8)
user version:        0
application id:      0
software version:    3042000
number of tables:    2
number of indexes:   2
number of triggers:  0
number of views:     0
schema size:         451
data version         1

写入量最大的三个数据库是per_poweroff.db 12万次,maca.db 50万次,per_reset.db 约4万次
maca.db结构简单,写入频繁的原因比较好定位,另外两个不好定位

maca.db

sqlite> .tables
t_maca_service  t_system_reset  t_watchdog
sqlite> select * from t_maca_service;
sqlite> select * from t_system_reset;
sqlite> select * from t_watchdog;
Id  LastWatchdogTime
--  ----------------
1   1778049279
sqlite> select * from t_watchdog;
Id  LastWatchdogTime
--  ----------------
1   1778049280
sqlite> select * from t_watchdog;
Id  LastWatchdogTime
--  ----------------
1   1778049283

可以发现就是maca组件每一秒记录一次喂狗时间导致的,感觉可以优化一下,每写一次都是至少4K的写入量。

求助内容

目前的数据库写入机制在频繁重启测试的情况下是不满足每天写入量低于800M的限制的,想确认一下这是否是正常现象,是否需要优化数据库写入

答案内容由AI生成,仅供参考:

:white_check_mark: 总结与回答您的疑问

“目前的数据库写入机制在频繁重启测试的情况下是不满足每天写入量低于800M的限制的,想确认一下这是否是正常现象,是否需要优化数据库写入?”

回答如下:

  1. 是否正常?

    • 1200次 Reboot 这种极端测试场景下,当前写入量(日均 > 4GB)虽“合理”,但暴露了设计缺陷
    • 真实业务场景中,此写入水平会显著缩短 NAND Flash 寿命(典型 TLC NAND P/E Cycle 为 1000~3000),不可接受
  2. 是否需要优化?

    • :white_check_mark: 必须优化!
    • 特别是 maca.db 的高频小写问题,属于典型的“可优化点”。
    • 建议将 每秒写入 改为 延迟合并写入仅在必要时写入,可降低90%以上写入量。
  3. 后续建议

    • NAND 写入量监控纳入自动化测试必检项
    • 推动建立 “高频写入组件清单”与“数据库访问规范”,防止类似问题复发。
    • 考虑在 Reboot 测试中 关闭非必要服务的日志/持久化行为,以隔离测试影响。
点击此处查看详细分析解答

关于1200次Reboot测试触发BMC NAND Flash写入量超限的分析与建议

根据您提供的问题描述和诊断信息,NAND Flash在15天内写入总量超过12GB,触发告警 0x1A000043: The data written to the NAND flash in last 15 days exceeds 12G 是由频繁的系统重启(Reboot)测试所引发的。以下将从告警机制、写入来源定位、根本原因分析及优化建议四个方面进行系统梳理。


:magnifying_glass_tilted_left: 一、告警机制解析:为何会触发“写入超限”?

1. 写入阈值设定

  • WriteThreshold = 12 GB
    该值为NAND Flash生命周期管理的核心阈值,定义了15天内允许的最大累计写入量
  • TotalWriteAmountIn15Days > WriteThreshold 时,系统上报轻微告警 0x1A000043

2. 实际写入数据确认

从您提供的命令输出可见:

WriteAmountPerDay=[4.52,4.506,4.57,4.34,2.961,0.314]  # 单日写入高达4.57GB
TotalWriteAmountIn15Days = 21.21 GB                  # 已远超12GB阈值

:backhand_index_pointing_right: 结论:此为真实写入过量告警,非误报。


:wrench: 二、写入来源定位:哪些进程/组件导致高写入?

通过分析 /proc/*/io 及数据库变更频率,已定位三大高频写入数据库文件:

数据库文件 路径 写入次数(file change counter) 持久化类型 用途简述
maca.db /opt/bmc/pram/persistence.local/maca.db ~507,668 次 ResetPer MAC地址管理、看门狗记录
per_poweroff.db /data/trust/persistence/per_poweroff.db ~120,134 次 PoweroffPer 掉电持久化配置数据
per_reset.db /opt/bmc/pram/persistence/per_reset.db ~37,564 次 ResetPer 复位级持久化状态

:white_check_mark: 关键发现:maca.db 每秒更新一次看门狗时间戳,是高频小写操作典型代表。

-- t_watchdog 表内容变化示例
Id  LastWatchdogTime
--  ----------------
1   1778049279
1   1778049280
1   1778049283  ← 时间间隔约1~3秒,符合“每秒喂狗”行为

:gear: 三、根本原因分析

1. maca.db 高频写入 → 主因

  • 行为特征maca 组件以约每秒1次的频率更新看门狗时间戳。
  • 写放大效应:SQLite 默认页大小为 4KB,即使只写几个字节,也会导致整个 page 缓冲刷新,产生 4KB/write × 50万次 ≈ 2GB 日写入量
  • 场景加剧:在 1200次 Reboot 测试中,每次重启均可能触发初始化、重连、状态同步等额外写操作,进一步放大写入总量。

2. per_poweroff.db 与 per_reset.db 写入 → 次要但不可忽视

  • per_poweroff.db(掉电持久化)
    • 存储关键配置(如IP、证书、策略等),重启过程中反复持久化配置项。
    • 若未使用批量事务或变更检测机制,可能导致“无变更也写入”现象。
  • per_reset.db(复位持久化)
    • 用于保存 BMC 复位后需保留的状态(如统计计数、临时标志位),部分服务可能在每次启动时写入状态。

3. 测试模式 vs 正常运行模式差异

维度 正常运行 1200次 Reboot测试
启动频率 低频(月级) 极高频(每5.5分钟一次)
状态写入 偶发 每次重启重写大量状态
数据库压力 极重
NAND Wear 可接受 超负荷

:backhand_index_pointing_right: 结论:当前写入量虽超标,但在极端测试场景下属于“人为放大”的结果,不代表常规使用异常。但仍暴露了数据库写入优化不足的问题。


:hammer_and_wrench: 四、优化建议与改进方向

:white_check_mark: 建议1:优化 maca.db 的看门狗写入频率

  • 问题:每秒写一次 t_watchdog 表,导致大量无意义的 NAND 写入。
  • 建议方案
    • 方案A(推荐):改为内存缓存 + 延迟刷盘
      • 在内存中缓存 LastWatchdogTime,仅在 系统即将关机、复位前周期性(如每30秒) 持久化一次。
    • 方案B:引入 SQLite WAL 模式 + PRAGMA 合理配置
      PRAGMA journal_mode = WAL;
      PRAGMA synchronous = NORMAL;
      PRAGMA cache_size = 2000;
      
      减少锁竞争和写放大。

:white_check_mark: 建议2:启用批量事务写入(Bulk Transaction)

对于有批量更新需求的服务(如 sensor、devmon、fructrl),应避免逐条提交。

// 示例:使用 db:tx() 批量提交
persistence_db.tx([&]() {
    for (auto& item : updates) {
        db.update(item);
    }
});

参考知识库中《【persistence】问题定位方法&FAQ》指出:“批量操作应使用框架提供的批量提交接口 db:tx(),避免频繁结构调整导致写入量过大。


:white_check_mark: 建议3:引入写入监控机制

  • 使用如下命令定期检查每日写入量:
    busctl --user get-property bmc.kepler.bmc_soc /bmc/kepler/Managers/1/NandFlash \
           bmc.kepler.Managers.NandFlash WriteAmountPerDay
    
  • 设置告警规则:单日写入 > 800MB 触发预警(业界常见标准)。

:white_check_mark: 建议4:评估持久化策略合理性

参考知识库中《持久化机制介绍》的分类:

类型 存储位置 掉电保留 适用场景
Memory 内存 :cross_mark: 临时状态
TemporaryPer tmpfs :cross_mark:(复位清) 进程重启保留
ResetPer pram :white_check_mark:(复位保留) 当前 maca.db 使用
PoweroffPer nandflash :white_check_mark:(掉电保留) 关键配置
  • 思考t_watchdog 是否真需要 ResetPer
    → 若仅用于运行时监控,可降级为 TemporaryPer,减少对 NAND 的依赖。

:white_check_mark: 总结与回答您的疑问

“目前的数据库写入机制在频繁重启测试的情况下是不满足每天写入量低于800M的限制的,想确认一下这是否是正常现象,是否需要优化数据库写入?”

回答如下:

  1. 是否正常?

    • 1200次 Reboot 这种极端测试场景下,当前写入量(日均 > 4GB)虽“合理”,但暴露了设计缺陷
    • 真实业务场景中,此写入水平会显著缩短 NAND Flash 寿命(典型 TLC NAND P/E Cycle 为 1000~3000),不可接受
  2. 是否需要优化?

    • :white_check_mark: 必须优化!
    • 特别是 maca.db 的高频小写问题,属于典型的“可优化点”。
    • 建议将 每秒写入 改为 延迟合并写入仅在必要时写入,可降低90%以上写入量。
  3. 后续建议

    • NAND 写入量监控纳入自动化测试必检项
    • 推动建立 “高频写入组件清单”与“数据库访问规范”,防止类似问题复发。
    • 考虑在 Reboot 测试中 关闭非必要服务的日志/持久化行为,以隔离测试影响。

:paperclip: 附录:相关参考依据

  • WriteThreshold 定义WriteThreshold=12GB 为 NAND Flash 写入告警阈值。
  • WriteAmountPerDay 来源:来自 bmc.kepler.Managers.NandFlash 对象,记录每日写入量。
  • 数据库持久化机制文档持久化机制介绍 & 【persistence】问题定位方法&FAQ
  • 定位工具参考/proc/*/io, sqlite3 .dbinfo, busctl get-property

如有进一步日志或需求,可继续深入分析具体服务的写入调用栈。

maca.db per_reset.db是复位持久化,挂载在 /dev/pramdisk0,与NandFlash无关,分析nandflash可以用iostat -d -k 1 看具体哪个分区的写入量大,关于per_poweroff.db,可以看persistence的一键收集,里面有各表和组件的写入统计