跑 SQLite 查询不及时使用 sqlite3_finalize() 的严重后果,望周知。

本事件已被我投稿至纯靠北工程师(「#純靠北工程師 7ib 」)。

教训是:用 SQLite 跑完「每一笔」查询之后一定要「立刻」用 sqlite3_finalize(StatementPointer) 释放运存,不然会产生连 Xcode Instruments 都抓不到的运存泄漏。

事情是这样:

为了因应 Apple 对 8GB 运存的病态执着, 我最近刚刚给威注音输入法的原厂词库格式由 JSON 升级至 SQLite 。

我是第一次用 SQLite ,看这篇学的(威注音是用 Swift 开发的): itisjoe.gitbooks.io/swiftgo/con... 现在 Swift 用 SQLite 超方便,直接 import SQLite3 就行。 ( Linux 或者旧版 macOS 还可以直接读 SQLite3 的 almagation 。) 只是,窃以为我犯的最大错误就是「没有针对相关的 SQLite API 详读 SQLite 官方的手册」。

我一开始以为让所有的 SQLite Statement 共用一个(作为静态变数的) nullable OpaquePointer 就可以了, 于是我一开始的设计就是让辞典模组在 deinit() 的时候才跑一次「 sqlite3_finalize()」。 因为原厂词库是只读的、在 App Bundle 内,所以我将 journal 塞在了运存内。

结果呢?施工完毕之后,单元测试啥的都成功通过了,刚刚开启输入法时的运存占用是 18MB 左右。 当时我感觉很开心,因为这几乎是直接消灭了输入法启动时花在原厂辞典上的载入时间。 但是,周一上午,我用这输入法没打六分钟的字,输入法碰到了我之前设定的保险丝而自尽了: 我早前做了这么个保险设计:只要运存占用超过 768MB ,输入法就自尽、自动重新启动来释放运存。

然后,我用 Xcode 14.2 的 Instruments 抓运存泄漏, 但只抓到一个与系统输入法选单有关的小微型泄漏(还是无法解决的那种)。 正好我周一那天公司休假,我花了一整个周一的时间排查自己做过的所有修改, 最后开始怀疑「 sqlite3_finalize()」是不是得在每次查询之后都执行一次。 于是我补上了这句试了试:

swift 复制代码
extension vChewingLM.LMInstantiator {
  fileprivate static func querySQL(strStmt sqlQuery: String, coreColumn column: CoreColumn, handler: (String) -> Void) {
    guard Self.ptrSQL != nil else { return }
    defer { sqlite3_finalize(Self.ptrStatement) } // 补上了这句。
    sqlite3_prepare_v2(Self.ptrSQL, sqlQuery, -1, &Self.ptrStatement, nil)
    while sqlite3_step(Self.ptrStatement) == SQLITE_ROW {
      guard let rawValue = sqlite3_column_text(Self.ptrStatement, column.id) else { continue }
      handler(String(cString: rawValue))
    }
  }
...
}

结果发现运存泄漏的问题失踪了。 这问题幸好发现得早,不然威注音 3.6.2 正式版带着这个 Bug 发出去的话会坑死很多人。

然后我就将这次经历投稿到靠北工程师,但没想到反应非常空前。 居然还有人说我积阴德。还有人在转发时提到这么个例子:

超市的系统在频繁的查询资料后都会有整个系统延迟的状况,不知道跟这有没关系... 虽然资料库跟我没啥屁关系,也先备份再说。

于是我决定将这个故事也放在掘金这边让各位 SQLite 用户共勉。

相关推荐
炬火初现43 分钟前
Etcd的安装与使用
数据库·etcd
IT猿手1 小时前
2025最新群智能优化算法:云漂移优化(Cloud Drift Optimization,CDO)算法求解23个经典函数测试集,MATLAB
开发语言·数据库·算法·数学建模·matlab·机器人
雷渊1 小时前
深入分析理解mysql的MVCC
java·数据库·面试
Paparazi灬1 小时前
RocksDB写流程各种场景下的处理逻辑和线程交互时序
数据库
神经星星2 小时前
【vLLM 教程】使用 TPU 安装
数据库·人工智能·机器学习
hjehheje2 小时前
clickhouse查询效率低
数据库·人工智能
七七powerful2 小时前
ClickHouse 中出现 DB::Exception: Too many parts 错误
java·前端·数据库
Linux运维老纪3 小时前
Python实战项目(‌Hands-on Python Project)
开发语言·数据库·python·sql·mysql·云计算·运维开发
小林熬夜学编程3 小时前
【MySQL】第十五弹---全面解析事务:定义、起源、版本支持与提交方式
android·linux·服务器·开发语言·数据库·mysql
明矾java10 小时前
MySQL进阶-关联查询优化
数据库·mysql