SQLite busy handler
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的更多相关文章
- 【腾讯Bugly干货分享】微信iOS SQLite源码优化实践
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57b58022433221be01499480 作者:张三华 前言 随着微信iO ...
- SQLite Design and Concepts
API 分为两大类 core API. 基本的SQL操作 extension API. 创建自定义的SQL操作. 基本数据结构 需要了解的组成部分有连接.statments.B树.pager. 为了写 ...
- SQLite剖析之内核研究
先从全局的角度把握SQLite内核各个模块的设计和功能.SQLite采用了层次化.模块化的设计,而这些使得它的可扩展性和可移植性非常强.而且SQLite的架构与通用DBMS的结构差别不是很大,所以它对 ...
- SQLite入门与分析(三)---内核概述(2)
写在前面:本节是前一节内容的后续部分,这两节都是从全局的角度SQLite内核各个模块的设计和功能.只有从全局上把握SQLite,才会更容易的理解SQLite的实现.SQLite采用了层次化,模块化的设 ...
- sqlite遇到database is locked问题的完美解决
这两天在项目中用大强度大频率的方法测试时遇到sqlite报database is locked的问题,分析下来原因是sqlite对数据库做修改操作时会做(文件)锁使得其它进程同一时间使用时会报该错误( ...
- 【原】FMDB源码阅读(一)
[原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...
- FMDB源码解析
上一篇博客讲述SQLite的使用,本篇将讲述FMDB源码,后面也会讲解SQLite在使用与FMDB的区别.本篇读下来大约20-30分钟,建议大家先收藏一下. FMDB是以OC方式封装SQLite中C语 ...
- Register A Callback To Handle SQLITE_BUSY Errors(译)
http://www.sqlite.org/c3ref/busy_handler.html留着自己看的. Register A Callback To Handle SQLITE_BUSY Error ...
- ArcGIS API For Android Errors汇总
API客户端异常错误的发生通常是由于不正确的方法参数,对象状态依赖,或网络条件. //*******推荐使用方法,按下Ctrl+F搜索错误代码,再查看与代码对应的解释.********// ArcGI ...
随机推荐
- java8--网络编程(java疯狂讲义3复习笔记)
重点复习一下网络通信和代理 java的网络通信很简单,服务器端通过ServerSocket建立监听,客户端通过Socket连接到指定服务器后,通信双方就可以通过IO流进行通信. 需要重点看的工具类:I ...
- bash builtin eval
1 在开始执行eval后面的命令之前eval主要做了哪些事情 1.1 去掉反斜杠的quoting 比如\$ac_optarg,会变成$ac_optarg. 1.2 去掉单引号的quoting 比如: ...
- HEX文件格式学习笔记
这也是一篇学习摘抄:原文地址:http://blog.csdn.net/syrchina/article/details/7004998 为了编写一个可以按照自己的要求进行ISP的程序, ...
- ubuntu12.04安装tftp,配置,修改目录,错误类型
[前言]学习嵌入式,需要配置tftp服务,在网上搜了搜,很多,但是配置了,我的老是出现Error code 1: File not found错误,经过探索和一个大哥的博客http://blog.cs ...
- POJ1661 Help Jimmy —— DP
题目链接:http://poj.org/problem?id=1661 Help Jimmy Time Limit: 1000MS Memory Limit: 10000K Total Submi ...
- 关于页面上输入框中 空格 、0 、NULL 的处理 示例
ep.setPositionNum(get("positionNum").toString()); ep.setClasstype(get("classtype" ...
- 并不对劲的bzoj4816:loj2000:p3704[SDOI2017]数字表格
题目大意 有函数\(f(x)\),\(f(0)=0,f(1)=1,f(x)=f(x-1)+f(x-2)\) \(t\)(\(t\leq1000\))组询问,每次给定\(n,m\)(\(n,m\leq1 ...
- openStack 镜像制作,镜像裁剪一般步骤
镜像制作一般裁剪步骤 1, linux系统安装CentOs/RHEL Desktop桌面系统,分区划分但分区/挂载点.设置Selinux=disabled关闭iptables安装cloud-init[ ...
- INT_PTR数据类型
A signed integer type for pointer precision. Use when casting a pointer to an integer to perform poi ...
- bootstrap 表单元素、按钮、链接的禁用
在Bootstra中,表单元素,按钮通过在标签内设置 disabled 或 disabled="disabled" 可以禁用表单元素,按钮.链接需要加入class="di ...