使用sqlite C ++库时,我可以使用/etc/init.d/apache2 restart
打开数据库。这将生成数据库的句柄,并将设置指向该句柄的指针。
使用该指针,我可以调用sqlite3_open_v2
来准备一个sqlite语句,然后我可以使用sqlite3_prepare_v2
来逐步查看查询结果。
现在,我正在一个环境中工作,我有多个不断创建和销毁的多个线程(它是一个服务器应用程序,它产生新的线程来提供传入的,可能是并发的连接)。现在,就我的理解而言,每次创建新线程时,我应该通过调用sqlite3_step
为同一个数据库创建新句柄。但是,这会增加显着的计算开销,因为创建与数据库的新连接可能需要一段时间,我需要处理 lot 连接。
所以我想知道是否有更有效的方法来实现这一目标。有没有办法,例如,只是互斥一切来解决我的问题?我可以将我的调用默认为我唯一的连接对象:这会将我与数据库的通信序列化。
这会有用吗?或者,为什么我不能从几个不同的线程使用相同的连接对象,即使我避免任何形式的并发?
如果这可行,我应该将我的来电序列化为sqlite3_open_v2
,还是第一次拨打sqlite3_prepare_v2
,或拨打sqlite3_step
的所有电话?我的意思是:当我第一次调用sqlite3_step
时,每次调用step
时都会加载所有结果或与实际数据库文件进行通信?
区别在于只对step
的调用进行静音,并锁定所有内容,直到我完成prepare
ping结果。
这样的事情是否可行,我是否应该每次只创建与数据库的新连接并让sqlite处理所有的并发性,或者我是否遗漏了一些重要的事情来解决我的问题?
答案 0 :(得分:2)
你可以让sqlite3为你处理所有这些,默认情况下它应该。 sqlite3库应该使用SQLITE_THREADSAFE=1
by default(empahsis mine):
SQLITE_THREADSAFE =< 0或1或2>
此选项控制SQLite中是否包含代码,以使其在多线程环境中安全运行。 默认值为SQLITE_THREADSAFE = 1 ,可安全地在多线程环境中使用。
并且SQL_CONFIG_SERIALIZED
也应该是used by default(强调我的):
SQLITE_CONFIG_SERIALIZED
这个选项没有参数。此选项将线程模式设置为Serialized。换句话说,此选项启用所有互斥锁,包括数据库连接和预准备语句对象上的递归互斥锁。 在此模式下(使用SQLITE_THREADSAFE = 1编译SQLite时的默认设置) SQLite库本身将序列化对数据库连接和预准备语句的访问,以便应用程序可以自由使用相同的数据库连接或同时在不同的线程中使用相同的预处理语句。
但是,您也可以使用call to sqlite3_config
before initialisation:
sqlite3_config(SQL_CONFIG_SERIALIZED);
然后,您应该open your database使用SQLITE_OPEN_FULLMUTEX
:
sqlite3* pDatabase;
sqlite3_open_v2("MyDatabase.db", &pDatabase, SQLITE_OPEN_FULLMUTEX, nullptr);
您也可以使用std::mutex
来阻止访问您的sqlite3调用,但这不是必需的,因为sqlite3会为您处理它(但如果由于某种原因您为某些人构建了不同的库)原因,这是可行的。)
答案 1 :(得分:0)
我认为您应该检查是否在sqlite3_config()
之后调用sqlite3_initialize()
函数。如果这样,函数sqlite3_config()
返回SQLITE_MISUSE。
以下是有关sqlite3-config()API的部分解释,其中涉及错误代码SQLITE_MISUSE。
sqlite3_config()
接口只能在使用sqlite3_initialize()进行库初始化之前或由sqlite3_shutdown()关闭后才能调用。如果在sqlite3_config()
之后和sqlite3_initialize()
之前调用sqlite3_shutdown()
,则它将返回SQLITE_MISUSE。但是请注意,sqlite3_config()
可以作为应用程序定义的sqlite3_os_init()的实现的一部分来调用。