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. JavaScript的高大强

    1,JavaScript的引入方式 1.1>Script标签内写代码 <Script> //这里写JS代码的地方 </Script> 1.2>引入额外的JS文件 & ...

  2. sqlite支持linq

    A small library to easily access SQLite databases from .NET/Mono/MonoTouch applications In order to ...

  3. 【转】使用git将项目上传到github(最简单方法)

    原文地址:http://www.cnblogs.com/cxk1995/p/5800196.html 首先你需要一个github账号,所有还没有的话先去注册吧! https://github.com/ ...

  4. 小程序-demo:天气预报

    ylbtech-小程序-demo:天气预报 1.返回顶部 1.app.js //app.js App({ //系统事件 onLaunch: function () {//小程序初始化事件 var th ...

  5. vue 随笔 vue 的属性和方法

    新建的项目中main.js是项目的入口文件 npm run dev 运行文件 npm run bulid  编译 属性与方法 每个Vue实例都会代理其 data 对象里所有的属性: var data= ...

  6. bzoj3090

    树形dp 有一个比较明显的dp状态是dp[i][j]表示当前i节点的子树已经满足且i剩下j元钱的最小操作次数,这样复杂度比较高状态数已经有O(n*x)的了,转移再来x,肯定不行. 我们考虑把状态和dp ...

  7. 微信公众号开发——创建自定义菜单(PHP版)

    <?php include "TokenUtil.php"; //TokenUtil::build_access_token(); $access_token = Token ...

  8. 代码中特殊的注释技术——TODO、FIXME和XXX的用处 (转载)

    转自:http://blog.csdn.net/reille/article/details/7161942 作者:reille 本博客网址:http://blog.csdn.net/reille/, ...

  9. bzoj 1079: [SCOI2008]着色方案【记忆化搜索】

    本来打算把每个颜色剩下的压起来存map来记忆化,写一半发现自己zz了 考虑当前都能涂x次的油漆本质是一样的. 直接存五个变量分别是剩下12345个格子的油漆数,然后直接开数组把这个和步数存起来,记忆化 ...

  10. js点赞浮动特效

    js自己封装的库: (function($) { $.extend({ tipsBox: function(options) { options = $.extend({ obj: null, //j ...