Linux /proc/sys/vm/drop_caches 的 flush cache 操作生产使用边界

2次阅读

不会丢应用数据,但会清空内核页缓存、目录项和inode缓存,仅影响已写入磁盘且未被修改的干净页,不触发writeback,不影响dirty page及数据库自身缓冲区。

Linux /proc/sys/vm/drop_caches 的 flush cache 操作生产使用边界

直接改 /proc/sys/vm/drop_caches 会立即丢数据吗?

不会丢应用数据,但会清空内核页缓存、目录项和 inode 缓存。它只影响已写入磁盘且未被修改的缓存页drop_caches 不触发 writeback,也不影响 dirty page。换句话说:正在写的文件、没 sync 的修改、数据库自己的 buffer 都不受影响——但后续读这些文件时会变慢,因为得重新从磁盘加载。

  • 这个操作本质是“让内核放弃它认为可以安全丢弃的缓存”,不是强制刷盘也不是清空所有内存
  • 必须用 echo 3 > /proc/sys/vm/drop_caches(或 1/2),仅 root 可写
  • 普通用户执行会报错:Permission denied
  • 它不等同于 sync && echo 3 > ...sync 是确保 dirty page 写盘,drop_caches 是之后才清理干净页

drop_caches=3mysqlpostgresql 场景下有什么副作用?

会让数据库下次查询响应明显变长,尤其在冷启动或大表扫描后手动清缓存时。PostgreSQL 的 shared_buffers 不受影响(那是自己管理的),但 OS page cache 里缓存的 WAL 文件、数据文件块会被清掉;MySQL 的 InnoDB Buffer Pool 同理独立,但 query cache(已弃用)或文件系统层预读缓存没了。

  • 如果刚做完 mysqldump 或逻辑备份,接着跑 drop_caches,后续恢复或导入会更慢
  • 备份工具如 percona-xtrabackup 依赖大量文件读取,清缓存后 IO 压力会瞬间拉高
  • drop_caches 对 LSM-tree 类引擎(如 RocksDB)影响较小,因为它们更依赖自身 block cache,而非 page cache

为什么 echo 3 > /proc/sys/vm/drop_caches 在容器里经常失效?

因为容器默认没有 sys_admin cap,且 /proc/sys/vm/ 是 host Namespace 的,容器进程即使挂载了该路径,写入也会被拒绝,报错:Operation not permitted

  • 即使你用 docker run --privileged,也得确认 cgroup v2 下是否放开了 vm.drop_caches 控制器(通常不开放)
  • kubernetes Pod 默认禁止该操作,除非显式加 securityContext.capabilities.add: ["SYS_ADMIN"],且节点允许
  • 更隐蔽的问题:某些发行版(如 RHEL/centos 8+)启用了 kernel.unprivileged_userns_clone=0,连 root 在 user namespace 里都写不了

替代 drop_caches 的更可控手段有哪些?

真要模拟“清缓存测性能”,优先考虑隔离测试环境,而不是在线生产清。线上唯一合理用途是排除 page cache 干扰后的 IO 性能对比,且必须配合监控确认无业务抖动。

  • posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED) 在应用层提示内核丢弃某文件缓存,比全局清更精准
  • 测试时用 stress-ng --vm 1 --vm-bytes 4G --vm-hang 0 --timeout 30s 占满内存再释放,效果接近但可逆
  • 真要清,务必先 echo 1 > /proc/sys/vm/compact_memory 防止内存碎片导致后续分配慢(尤其在低内存压力下)

有些团队把 drop_caches 当“重启前清理”用,其实是在掩盖内存泄漏或 buffer 配置不合理的问题。它不解决根本,只掩盖症状,而且时机稍有偏差就可能卡住 IO 调度器几秒。

text=ZqhQzanResources