我将从 TL;DR 版本开始,因为这对你们中的一些人来说可能已经足够了:
- 我们正在尝试调查我们在 C++ 产品的诊断数据中看到的问题。
- 该问题被确定是由超时引起的
sqlite3_open_v2,据称超时时间超过 60 秒(我们只给它 60 秒)。 - 我们尝试了多种不同的配置,但在此调用中甚至无法重现 5 秒的延迟。
所以问题是,是否有一些已知的场景sqlite3_open_v2可能需要这么长时间(在 Windows 上)?
现在到细节:
- 我们使用
3.10.2的是 SQLite 版本。到目前为止,我们浏览了这个版本的变更日志,我们在错误修复部分中没有发现任何东西似乎表明在连续的 SQLite 版本中已经解决了一些问题,并且可能导致了我们的问题。 - 我们看到的问题影响了所有受支持的 Windows 版本(Win 7、Win 8、Win 10)中大约 0.1% 的唯一用户。没有关于此的手动用户投诉/报告 - 这可能表明问题发生在用户机器/系统发生足够严重的事情而他不期望任何工作的情况下。因此,只要 0.1% 的随机 Windows 用户可能发生这种情况,表明系统范围内的故障是一种有效的可能性。
- 没有数据表明 Mac 上曾经发生过同样的问题,Mac 也是具有足够大诊断数据样本的支持平台。
- 我们正在使用 Poco(https://github.com/pocoproject/poco,版本:1.7.2)作为访问我们的 SQLite 数据库的工具,但是我们已经分析了 Poco 代码,似乎这个代码级别的失败可以仅(可能)解释约 1% 的所有收集的样本。这就是我们如何确定问题在于
sqlite3_open_v2花费很长时间的方式。 - 这发生在
DELETE日志模式和WAL. - 似乎在特定用户第一次发生此问题后,每次连续调用都
sqlite3_open_v2需要很长时间,直到用户重新启动整个应用程序(可能是机器,无法从我们的数据中分辨出来)。 - 我们正在使用以下标志设置
sqlite3_open_v2(如在 Poco 中):
sqlite3_open_v2(..., ..., SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI, NULL);
- 这通常不会在应用程序启动时发生,因此它不太可能是由我们的应用程序未运行时发生的事情引起的。这包括导致数据破坏的断电(无论如何都会返回 SQLITE_CORRUPT,如https://www.sqlite.org/howtocorrupt.html中所述)。
即使我们尝试了不同的方法,我们也无法在本地重现此问题:
- 多个线程在特定日志系统所需的同步下从 DB 写入和读取。
- 保持 SQLite 连接长时间打开,同时在 DB 上正常工作。
- 试图用其他数据重击 HDD(在正常访问数据库时将 /dev/rand (WSL) 转储到来自不同进程的多个文件)。
- 试图强制防病毒软件在每次文件访问时扫描数据库(使用 Avast 进行测试,基本上所有功能都启用,包括“打开时扫描”和“写入时扫描”)。
- 打破特定日志系统所需的内部同步。
- 使用 DB 文件上所有可能的文件共享选项组合调用 WinAPI CreateFile - 这会导致问题,但
sqlite3_open_v2总是快速返回 - 只是出现错误。 - 顺便说一句,在 DB 文件的随机部分上调用 WinAPI LockFile。重现的好方法
SQLITE_IOERR,但重现讨论的问题没有运气。 - 一些额外的尝试来实际拉伸 Poco 层并仔细检查我们对代码的静态分析是否正确。
我们试图在网上寻找类似的问题,但我们发现的任何相关的东西都在这里sqlite3-open-v2-performance-degrades-as-number-of-opens-increase。但这似乎并不能解释我们的情况,因为并行连接的数量远远超出了我们所拥有的以及典型的 Windows 用户所拥有的数量(除非有一些我们不知道的利用 SQLite 的流行应用程序) .
- 这个问题不太可能是由通过网络共享访问 db 引起的,因为我们将 DB 文件放入其中
%appdata%,除非有一些非常标准的 Windows 配置设置%appdata%为远程共享。
你有什么想法会导致这个问题吗?
也许一些关于我们应该检查什么或我们可以从用户那里收集到的额外诊断数据的一些提示将有助于查明发生这种情况的真正原因?
提前致谢