SQLite 中的并发读/写会破坏读取结果?

问题描述 投票:0回答:1

我有一个多线程应用程序,它使用 SQLite DB 进行持久存储。 该应用程序使用一个持久连接。 它在启动时和每次回滚后准备语句。它还使用

journal_model=WAL
来帮助并发访问。

我发现当我的

listUsers()
函数被同时调用时,有时结果似乎会在调用之间泄漏。 我知道有 100 个用户,但有时结果是 100+,我认为这是因为一个线程上的
sqlite3_step
正在从本来可以在另一个线程上调用的
sqlite3_step
中提取结果。 这可能吗?

另外,我尝试将

listUsers()
包装在事务中,但有时它会抛出错误,表明一个事务正在另一个事务中启动。 同样,我认为这是因为两个线程共享同一个数据库连接。

这个问题有通用的解决方案吗? 每个线程一个连接? 我不太关心偶尔锁定的数据库或长时间的等待,这只是令人担忧的无效结果。

如果有帮助,我的

listUsers()
看起来像

std::vector<User> listUsers()
{
    char* err = 0;
    auto users = std::vector<User>();
    sqlite3_reset(list_user_stmt);
    beginTransaction();
    while (SQLITE_ROW == sqlite3_step(list_user_stmt))
    {
        auto id = sqlite3_column_int(list_user_stmt, 0);
        auto name = sqlite3_column_text(list_user_stmt, 1);
        users.push_back(User{id, name});
    }
    commitTransaction();
    return users;
}
c++ multithreading sqlite
1个回答
0
投票

您不能同时从多个线程使用同一个连接。 SQLite 数据库对于并发访问是安全的,但单个连接则不然(据我所知,它将是“线程安全”,因为它实际上不会损坏任何数据,但它的行为不会像你一样)在这种情况下,我们希望 – 特别是单个连接之间没有事务隔离,因为这实际上没有任何意义)。如果您需要同时从多个线程访问该线程,您可以在连接上放置一个互斥体,并且在任何时候只有一个线程访问数据库(通常 SQLite 不需要,但如果例如您缓存在应用程序级别的一些结果中,您可能需要这样做以保持缓存的视图一致),每个线程都有一个连接,或者如果您有很多线程,则使用连接池作为合理的中间立场。

© www.soinside.com 2019 - 2024. All rights reserved.