我在 Windows 7 上使用版本 3.21.0 的 sqlite3 库。以及版本 1.0.0.0 的 SQLite Studio
我有几个进程将要在 sqlite3 表中处理的数据排队。当有数据要排队时,打开一个数据库连接,将一条记录插入到表中,然后关闭数据库连接。多个线程可以在每个进程中插入记录,但连接不共享。它为每个插入打开和关闭。每次将记录插入表中时,都会发出一个 Windows 事件 (::OpenEvent) 信号,以便其他进程可以处理数据。
然后我有其他进程一次从表中提取一个记录来处理它们。他们打开一个连接,选择一条记录并在事务(BEGIN/COMMIT)中删除它以进行处理。每个进程中只有一个线程用于处理数据。读取并处理完所有记录后,连接将关闭,直到通过 Windows 事件发出信号表明有更多记录要处理。
如果任何进程返回 SQLITE_BUSY,则该进程将继续重试,直到成功。
在处理了大约 1,300 条记录(每秒插入 2-3 条记录),其中 4 个进程插入记录和两个进程选择和删除它们之后,我在 SQLite Studio 中注意到从未处理过三个记录。似乎 sqlite3.dll 由于某种原因无法看到这些记录,但 SQLite Studio 可以。
当我在 SQLite Studio 下面的代码示例中运行 SELECT 语句时,我可以看到三个记录。但是,当我对带有 sqlite3.dll 的同一个数据库使用相同的 SELECT 语句时,我没有得到任何记录。
下面的 sqlite3_step 在应该返回 SQLITE_ROW 时返回 SQLITE_DONE。
我把下面的测试放在一起来证明这个问题。
#include "stdafx.h"
#include <Windows.h>
#include <sqlite3.h>
#include <crtdbg.h>
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hModule = ::LoadLibraryW(L"sqlite3.dll") ;
sqlite3* db ;
int rc = ::sqlite3_open16(L"mydatabase.db", &db) ;
_ASSERTE(SQLITE_OK == rc) ;
_ASSERTE(db != NULL) ;
sqlite3_stmt* stmt = NULL ;
rc = ::sqlite3_prepare_v2(db, "SELECT * FROM MYTABLE;", -1, &stmt, NULL) ;
_ASSERTE(SQLITE_OK == rc) ;
_ASSERTE(stmt != NULL) ;
rc = ::sqlite3_step(stmt) ;
_ASSERTE(SQLITE_ROW == rc) ;
rc = ::sqlite3_finalize(stmt) ;
_ASSERTE(SQLITE_OK == rc) ;
rc = ::sqlite3_close_v2(db) ;
_ASSERTE(SQLITE_OK == rc) ;
return 0;
}
我只是将 sqlite 集成到我们的产品中,并试图证明这个概念。显然,我担心数据的完整性。SQLite Studio 是否以某种方式看到被删除的记录?还是 sqlite3.dll 没有看到那里的记录?我的数据库是否已损坏,我应该怎么做才能防止这种情况发生?我不相信我在做任何过于复杂的事情。这是一个简单的打开、插入、关闭。如果返回 SQLITE_BUSY,则在短暂睡眠后重试。然后它,打开,开始;选择; 删除; 在另一边提交。如果返回 SQLITE_BUSY 并在短暂睡眠后重试,则 ROLLBACK 而不是 COMMIT。
建议?