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. 查看android-support-v4.jar引出的问题

    1.前面博文里也写过如何关联android-support-v4.jar的源码 今天新项目用上述方法的时候,竟然不成功..来回反复试了很长时间,最后发现 新建项目,会自动引用一个类库(自动新建的..) ...

  2. cygwin安装sshd服务(win7)Error installing a service: OpenSCManager: Win32 error 5:

    Error installing a service: OpenSCManager: Win32 error 5:           出现这个问题的解决办法:win7系统管理员运行Cygwin软件 ...

  3. ES6 模块化(Module)export和import详解 export default

    ES6 模块化(Module)export和import详解 - CSDN博客 https://blog.csdn.net/pcaxb/article/details/53670097 微信小程序笔记 ...

  4. JSON: Circular Dependency Errors

    If you’re using Object Relational Mapping frameworks like Hibernate, and are using the bi-directiona ...

  5. POJ - 1470 Closest Common Ancestors(离线Tarjan算法)

    1.输出测试用例中是最近公共祖先的节点,以及这个节点作为最近公共祖先的次数. 2.最近公共祖先,离线Tarjan算法 3. /* POJ 1470 给出一颗有向树,Q个查询 输出查询结果中每个点出现次 ...

  6. ios app 上架AppStore

    一.证书的导出      1.1 前期工作        首先你需要有一个苹果的开发者帐号,一个Mac系统.        如果没有帐号可以在打开http://developer.apple.com/ ...

  7. Code Project精彩系列(转)

    Code Project精彩系列(转)   Code Project精彩系列(转)   Applications Crafting a C# forms Editor From scratch htt ...

  8. appium学习【五】【转】appium实现屏幕向左滑动

    转自http://www.cnblogs.com/testhub/p/5949668.html 前些日子写一个滑动手机页面的小脚本,看到大家给的内容都是swipe方法,这里对swipe方法做一个小介绍 ...

  9. 【转】解决从jenkins打开robot framework报告会提示‘Opening Robot Framework log failed ’的问题

    最新的jenkins打开jenkins robot framework报告会提示如下 Verify that you have JavaScript enabled in your browser.  ...

  10. 【415】C语言文件读写

    A program can open and close, and read from, and write to, a file that is defined by the user This i ...