SQLite doesn't support high concurrency. In case of a lot of concurrent access from multi-process or multi-thread, calling a SQLite r/w function is prone to hit the case that the database is locked by another process or thread. The default behavior is that the SQLite r/w function return SQLITE_BUSY immediately, and the caller should retry the call later.

Below is an example function. When the SQLite function returns SQLITE_BUSY, the caller sleep one second then retry. The sleep is required to optimize the CPU utilization, without the sleep, the CPU will be occupied by a lot of retries.

bool Execute(const string& sql) {
char* errmsg = NULL;
while (true) {
int status = sqlite3_exec(db_, sql.c_str(), NULL, NULL, &errmsg);
if (status == SQLITE_OK) {
return true;
} else if (status == SQLITE_BUSY) {
++total_busycount;
cerr << "Thread " << threadindex_ << ": failed to execute " << sql << " (" << errmsg << ")\n";
sqlite3_free(errmsg);
sleep(1);
} else {
cerr << "Thread " << threadindex_ << ": failed to execute " << sql << " (" << errmsg << ")\n";
sqlite3_free(errmsg);
return false;
}
}
return false;
}

In fact, the caller doesn't need to sleep explicitly, calling sqlite3_busy_timeout before SQLite r/w functions will make SQLite automaticlly insert sleep between two sequential calls of a r/w function. It's safe to set a big timeout value. SQLite splits the big timeout value into many small timeout values. With the optimization, if the lock is available while the caller is waiting, the caller won't need to wait to timeout. See below code,

1452  static int sqliteDefaultBusyCallback(
1453 void *ptr, /* Database connection */
1454 int count /* Number of times table has been busy */
1455 ){
1456 #if SQLITE_OS_WIN || HAVE_USLEEP
1457 static const u8 delays[] =
1458 { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
1459 static const u8 totals[] =
1460 { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
1461 # define NDELAY ArraySize(delays)
1462 sqlite3 *db = (sqlite3 *)ptr;
1463 int timeout = db->busyTimeout;
1464 int delay, prior;
1465
1466 assert( count>=0 );
1467 if( count < NDELAY ){
1468 delay = delays[count];
1469 prior = totals[count];
1470 }else{
1471 delay = delays[NDELAY-1];
1472 prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
1473 }
1474 if( prior + delay > timeout ){
1475 delay = timeout - prior;
1476 if( delay<=0 ) return 0;
1477 }
1478 sqlite3OsSleep(db->pVfs, delay*1000);
1479 return 1;
1480 #else
1481 sqlite3 *db = (sqlite3 *)ptr;
1482 int timeout = ((sqlite3 *)ptr)->busyTimeout;
1483 if( (count+1)*1000 > timeout ){
1484 return 0;
1485 }
1486 sqlite3OsSleep(db->pVfs, 1000000);
1487 return 1;
1488 #endif
1489 }

Another alternative is set a busy hander by calling sqlite3_busy_handler. If the busy callback returns 0, then no additional attempts are made to access the database and SQLITE_BUSY is returned to the application. If the callback returns non-zero, then another attempt is made to access the database and the cycle repeats.

SQLite busy handler的更多相关文章

  1. 【腾讯Bugly干货分享】微信iOS SQLite源码优化实践

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57b58022433221be01499480 作者:张三华 前言 随着微信iO ...

  2. SQLite Design and Concepts

    API 分为两大类 core API. 基本的SQL操作 extension API. 创建自定义的SQL操作. 基本数据结构 需要了解的组成部分有连接.statments.B树.pager. 为了写 ...

  3. SQLite剖析之内核研究

    先从全局的角度把握SQLite内核各个模块的设计和功能.SQLite采用了层次化.模块化的设计,而这些使得它的可扩展性和可移植性非常强.而且SQLite的架构与通用DBMS的结构差别不是很大,所以它对 ...

  4. SQLite入门与分析(三)---内核概述(2)

    写在前面:本节是前一节内容的后续部分,这两节都是从全局的角度SQLite内核各个模块的设计和功能.只有从全局上把握SQLite,才会更容易的理解SQLite的实现.SQLite采用了层次化,模块化的设 ...

  5. sqlite遇到database is locked问题的完美解决

    这两天在项目中用大强度大频率的方法测试时遇到sqlite报database is locked的问题,分析下来原因是sqlite对数据库做修改操作时会做(文件)锁使得其它进程同一时间使用时会报该错误( ...

  6. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  7. FMDB源码解析

    上一篇博客讲述SQLite的使用,本篇将讲述FMDB源码,后面也会讲解SQLite在使用与FMDB的区别.本篇读下来大约20-30分钟,建议大家先收藏一下. FMDB是以OC方式封装SQLite中C语 ...

  8. Register A Callback To Handle SQLITE_BUSY Errors(译)

    http://www.sqlite.org/c3ref/busy_handler.html留着自己看的. Register A Callback To Handle SQLITE_BUSY Error ...

  9. ArcGIS API For Android Errors汇总

    API客户端异常错误的发生通常是由于不正确的方法参数,对象状态依赖,或网络条件. //*******推荐使用方法,按下Ctrl+F搜索错误代码,再查看与代码对应的解释.********// ArcGI ...

随机推荐

  1. 2016/3/27 PHP中include和require的区别详解

    1.概要 require()语句的性能与include()相类似,都是包括并运行指定文件.不同之处在于:对include()语句来说,在执行文件时每次都要进行读取和评估:而对于require()来说, ...

  2. egrep grep -E

    egrep执行效果与"grep-E" Linux egrep命令用于在文件内查找指定的字符串. egrep执行效果与"grep-E"相似,使用的语法及参数可参照 ...

  3. The input stream is not a valid binary format.

    The input stream is not a valid binary format. The starting contents (in bytes) are: 53-79-73-74-65- ...

  4. YTU 2432: C++习题 对象数组输入与输出

    2432: C++习题 对象数组输入与输出 时间限制: 1 Sec  内存限制: 128 MB 提交: 1603  解决: 1152 题目描述 建立一个对象数组,内放n(n<10)个学生的数据( ...

  5. YTU 2598: 编程题B-小平智斗自动售货机

    2598: 编程题B-小平智斗自动售货机 时间限制: 1 Sec  内存限制: 128 MB 提交: 268  解决: 69 题目描述 LYH自动售货机在销售商品时,具有自动找钱功能.但是找零的最小单 ...

  6. YTU 1003: Redraiment的遭遇

    1003: Redraiment的遭遇 时间限制: 1000 Sec  内存限制: 128 MB 提交: 198  解决: 71 题目描述 Redraiment的老家住在工业区,日耗电量非常大.是政府 ...

  7. Outlook 2007 发送邮件

    4 登入以投票 Hi, http://social.msdn.microsoft.com/Forums/zh-TW/6c063b27-7e8a-4963-ad5f-ce7e5ffb2c64/how-t ...

  8. asp.net mvc5 使用百度ueditor 本编辑器完整示例(三)在IIS中多个应用程序使用多个ueditor对象

    最近做了一个项目,要求同一类型的多个专业应用程序(网站),但是每个应用程序都需要调用各自当中的ueditor. 步骤: 一.在vs2013中设置每个专业的asp.net mvc 应用程序. 1.配置根 ...

  9. bzoj 3503: [Cqoi2014]和谐矩阵【高斯消元】

    如果确定了第一行,那么可以推出来整个矩阵,矩阵合法的条件是n+1行全是0 所以推出来n+1行和1行的关系,然后用异或高斯消元来解即可 #include<iostream> #include ...

  10. css覆盖select样式并添加小箭头

    .select { border-radius: 5px; border: 1px #F4A627 solid; -webkit-appearance: none;//清除默认样式 backgroun ...