嵌入式 关于sqlite多线程编程相关小结

嵌入式 关于sqlite多线程编程相关小结,第1张

概述相关接口说明: sqlite3_open() 通常这个函数被第一个调用,这个 *** 作打开一个数据库文件的链接,输出一个database connection对象,database connection对象在调用之后的接口时使用。 函数原型: int sqlite3_open( const char *filename, /*Database filename (UTF-8) */ sqlite3 **

相关接口说明:


sqlite3_open()
通常这个函数被第一个调用,这个 *** 作打开一个数据库文件的链接,输出一个database connection对象,database connection对象在调用之后的接口时使用。
函数原型:
int sqlite3_open(
const char *filename,/*Database filename (UTF-8) */
sqlite3 **ppDb /* OUT:sqlite db handle */
);
int sqlite3_open16(
const voID *filename,/*Database filename (UTF-16) */
sqlite3 **ppDb /* OUT:sqlite db handle */
);
int sqlite3_open_v2(
constchar *filename,/* Database filename(UTF-8) */
sqlite3 **ppDb,/* OUT:sqlite db handle */
intflags,/* Flags */
const char *zVfs /* name ofVFS module to use */
);
通过filename参数指定要打开的数据库,sqlite3_open()和sqlite3_open_v2()的filename参数是utf8编码格式,sqlite3_open16()的filename参数是UTF-16编码。
如果成功,sqlite3*被创建,返回值sqlITE_OK,如果失败,返回错误码,调用sqlite3_errmsg() 或 sqlite3_errmsg16()将得到错误信息。
无论成功与否, database connection句柄资源已经被分配,在不使用时应该将数据库连接句柄传递给sqlite3_close()释放资源。

sqlite3_open_v2的第三个参数,有3个值和其他的值(sqlITE_OPEN_NOMUTEX,sqlITE_OPEN_FulLMUTEX,sqlITE_OPEN_SHAREDCACHE,sqlITE_OPEN_PRIVATECACHE,and/or sqlITE_OPEN)组合:
sqlITE_OPEN_Readonly
sqlITE_OPEN_READWRITE
sqlITE_OPEN_READWRITE | sqlITE_OPEN_CREATE
如何不是用上面的3个值之一和其他值组合,其行为是未定义的。

sqlite3_prepare()
这个 *** 作第一个参数输入database connection对象,第二个参数输入SQL语句,该接口将输入的SQL语句转变成prepared statement对象,输出prepared statement对象,在调用之后的接口时使用,记住,这个函数不执行SQL语句,只为执行sql做准备。
函数原型:
int sqlite3_prepare(
sqlite3 *db,/*Database handle */
const char *zsql,/* sqlstatement,UTF-8 encoded */
intnByte,/* Maximum length ofzsql in bytes. */
sqlite3_stmt **ppStmt,/* OUT:Statement handle */
const char **pzTail /* OUT:Pointer to unused portion of zsql */
);
int sqlite3_prepare_v2(
sqlite3 *db,/* Maximum length of zsql in bytes. */
sqlite3_stmt **ppStmt,/* OUT:Statement handle */
const char **pzTail /* OUT:Pointer to unused portion of zsql */
);
int sqlite3_prepare16(
sqlite3 *db,/*Database handle */
const voID *zsql,UTF-16 encoded */
intnByte,/* OUT:Statement handle */
const voID **pzTail /* OUT:Pointer to unused portion of zsql */
);
int sqlite3_prepare16_v2(
sqlite3 *db,/* OUT:Statement handle */
const voID **pzTail /* OUT: Pointer to unused portion of zsql*/
);

sqlite3_step()
这个 *** 作执行sqlite3_prepare()接口返回的prepared statement,如果是SELECT *** 作,结果集的第一行将被返回,如果想得到第二行,还须再调用一次该函数,也就是每调用一次返回一行,直到完成。
有些 *** 作仅需调用1次该函数,如:INSERT,UPDATE,DELETE语句。
使用老接口得到的statement,执行sqlite3_step返回sqlITE_BUSY,sqlITE_DONE,sqlITE_ROW,sqlITE_ERROR,or sqlITE_MISUSE;
使用v2接口得到的statement,执行sqlite3_step返回任意的result code或extended result codes。

sqlite3_column()
sqlite3接口并没有sqlite3_column()函数,这里所说的是一组函数:
sqlite3_column_blob()
sqlite3_column_bytes()
sqlite3_column_bytes16()
sqlite3_column_count()
sqlite3_column_double()
sqlite3_column_int()
sqlite3_column_int64()
sqlite3_column_text()
sqlite3_column_text16()
sqlite3_column_type()
sqlite3_column_value()
这个 *** 作输入执行过sqlite3_step()的prepared statement对象,返回单列的结果,要得到一行中全部列的值需要调用多次这个函数。

sqlite3_finalize()
销毁之前调用sqlite3_prepare()创建的prepared statement,prepared statement必须由该函数销毁,否则会导致内存泄露。

sqlite3_close()
关闭之前调用sqlite3_open()创建的database connection,在调用该函数之前,必须保证所有的prepared statements都被finalized。

开发sqlite应用一般的流程:
首先用sqlite3_open()创建一个数据库连接,该函数根据输入参数可以打开一个已存在的数据库,也可以创建一个新的数据库文件。不用数据库的时候记得调用 sqlite3_close() 关闭数据库连接。
执行一个sql statement,有以下步骤:
1. 调用sqlite3_prepare()创建 preparedstatement。
2. 调用sqlite3_step()一次或多次执行preparedstatement。
3. 对于查询 *** 作,在两次sqlite3_step()之间调用sqlite3_column()获取结果。
4. 调用sqlite3_finalize()销毁preparedstatement。

在调用 sqlite3_step()之后,可以调用sqlite3_reset()初始化prepared statement。
很多时候,每次调用的SQL语句都是相似的,比如使用INSERT语句,每次执行只是插入不同的值,为了适应这种灵活性,sqlite允许sql statements带参数,在执行statements前给这些参数绑定一个值,绑定的值在 prepared statement第二次执行的时候还可以改变。

获得错误信息的函数:
int sqlite3_errcode(sqlite3 *db);
int sqlite3_extended_errcode(sqlite3 *db);
const char *sqlite3_errmsg(sqlite3*);
const voID *sqlite3_errmsg16(sqlite3*);

三.sqlite3的线程模式
sqlite支持3种不同的线程模式:
Single-thread:这种模式下,所有的互斥被禁用,多线程使用sqlite是不安全的。
Multi-thread:这种模式下,sqlite可以安全地用于多线程,但多个线程不能共享一个database connect。
Serialized:这种模式下,sqlite可以安全地用于多线程,无限制。

sqlite线程模式的选择可以在编译时(当sqlitelibrary 源码被编译时)或启动时(使用sqlite的应用初始化时)或运行时(新的 database connection被创建时)。
一般来说,运行时覆盖启动时,启动时覆盖编译时,不过,Single-thread模式一旦被选择了,就不能被重改。

编译时设置线程模式:
用sqlITE_THREADSAFE选择线程模式,
如果sqlITE_THREADSAFE没有被设置或设置了-DsqlITE_THREADSAF=1,则是Serialized模式;
如果设置了-DsqlITE_THREADSAF=0,线程模式是Single-thread;
如果设置了-DsqlITE_THREADSAF=2,线程模式是Multi-thread.

启动时设置线程模式:
假设编译时线程模式被设置为非Single-thread模式,在初始化时可以调用sqlite3_config()改变线程模式,参数可以为sqlITE_CONfig_SINGLETHREA,sqlITE_CONfig_MulTITH,sqlITE_CONfig_SERIAliZED.

运行时设置线程模式:
如果Single-thread模式在编译时和启动时都没被设置,则可以在database connections被创建时设置Multi-thread或Serialized模式,但不可以降级设置为Single-thread模式,也不可以升级编译时或启动时设置的Single-thread模式。
sqlite3_open_v2()的第三个参数决定单个databaseconnection的线程模式,sqlITE_OPEN_NOMUTEX使database connection为Multi-thread模式,sqlITE_OPEN_FulLMUTE使database connection为Serialized模式。
如果不指定模式或使用sqlite3_open()或sqlite3_open16()接口,线程模式为编译时或启动时设置的模式。

在IOS上的示例:
先说下初衷吧,实际上我经常看到有人抱怨sqlite不支持多线程。而在iOS开发时,为了不阻塞主线程,数据库访问必须移到子线程中。为了解决这个矛盾,很有必要对此一探究竟。

关于这个问题,最权威的解答当然是sqlite官网上的“Is SQLite threadsafe?”这个问答。
简单来说,从3.3.1版本开始,它就是线程安全的了。而
iOS的SQLite版本没有低于这个版本的:

3.4.0 - iPhone OS 2.2.1
3.6.12 - iPhone OS 3.0 / 3.1
3.6.22 - iPhone OS 4.0
3.6.23.2 - iPhone OS 4.1 / 4.2
3.7.2 - iPhone OS 4.3
3.7.7 - iPhone OS 5.0
当然,你也可以自己编译最新版本。只是我发现自己编译出来的3.7.8居然比iOS 4.3.3内置的3.7.2慢了一半,不知道苹果做了什么优化。 总结

以上是内存溢出为你收集整理的嵌入式 关于sqlite多线程编程相关小结全部内容,希望文章能够帮你解决嵌入式 关于sqlite多线程编程相关小结所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/1171750.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-02
下一篇 2022-06-02

发表评论

登录后才能评论

评论列表(0条)

保存