SQLite有个多数人没注意到的性能陷阱:每开一个数据库连接,它就默默复制一份完整的数据页缓存。你的App开了5个连接?同样的数据可能在内存里躺了5遍。这在桌面端无所谓,到了手机端就成了隐形杀手。
Shared Page Cache就是为此设计的。它不是新功能,但确实被低估了。打开后,同一进程内的多个连接会共享同一份页缓存和模式缓存。第一个连接把数据读进内存,后面的连接直接复用,不用再跑一趟磁盘。
![]()
实现机制比想象得精巧。每个连接仍保留独立的B-tree结构——这保证了隔离性——但这些B-tree都指向同一个BtShared对象。BtShared里藏着pager,也就是真正管缓存的那个角色。SQLite内部维护了一个共享结构列表,新连接进来时先查表,命中就挂靠,没命中才新建。
开启方式极简:一行sqlite3_enable_shared_cache(1)。关闭传0。但注意作用域——只在进程内生效,跨进程该咋锁还咋锁,走标准文件锁。
共享之后必然带来并发问题。SQLite的解决方案是分层加锁:写操作串行化,读操作可并行。具体到表级别,共享缓存模式下会引入额外的锁定粒度,防止多个连接同时写同一张表。
这个设计最聪明的地方在于权衡。它没有为了追求极致性能而牺牲隔离性,也没有为了简单而让内存白白浪费。对于读多写少、多连接并发的场景——比如移动端App同时处理UI查询和后台同步——收益很明显:内存下来了,磁盘I/O少了,响应更快了。
当然,不是银弹。写密集型负载、跨进程架构、或者对延迟极度敏感的场景,可能反而受限于额外的锁开销。但多数应用其实没开到那么多连接,也触不到瓶颈。真到了那一步,至少你知道有个开关可以试。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.