索引构建程序用 mmap 写完 200MB,退出后重新打开还是旧内容。dmesg 里没有报错,文件 mtime 也没变,只有进程自己读得到新数据。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,映射区的修改落在页缓存,进程退出只是解除映射,回写由内核择机做。没有 msync 就断电或换机器,改动全部丢失,文件长度也可能还是旧值。
碰到「mmap 未落盘」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
with open('index.bin', 'r+b') as f:
mm = mmap.mmap(f.fileno(), 0)
mm[:] = payload
mm.flush()
mm.close()
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
具体做法是,修改完调用 mmap.flush() 或 os.msync 指定 MS_SYNC;写完更新文件长度用 truncate 再 flush;关闭前先 flush 再 close 顺序别反;验证时另起进程读一遍 不要在原进程里确认。
最后用这个标准收尾,另起一个进程读文件 md5 和写入值一致 重启后索引仍然可用。
