sqlite遇到database is locked问题的完美解决
这两天在项目中用大强度大频率的方法测试时遇到sqlite报database is locked的问题,
分析下来原因是sqlite对数据库做修改操作时会做(文件)锁使得其它进程同一时间使用时会报该错误(也就是
SQLITE_BUSY),但如果仅是多进程或多线程查询sqlite是支持的。(也有可能是做sql开启事务查询等发生异常,数据库没有关闭,然后再去打开就锁定了)
解决方法有:
1。使用进程或线程间的同步机制以避免同时操作;如用信号量,互斥锁等(pthread_mutex_lock,
pthread_mutex_unlock),如果你的项目工程较大要求较高的话建议用此方法自行封装函数处理同步
2。使用sqlite提供的两个busy handler函数,但对于一个连接来说,只能有一个busy handle,两个函数会相互影响,设
置一个的同时会清除另一个,应根据需要来选择。
int sqlite3_busy_handler(sqlite3 *, int (*)(void *, int), void *)
不注册此函数时默认回调函数为NULL,清除busy handle,申请不到锁直接返回;
函数可以定义一个回调函数,当出现数据库忙时sqlite会调用该函数进行延时并返回非0会重试本次操作,回调函数的第二个
参数会被传递为此次因BUSY忙事件而调用该函数的次数,因此你完全可以自行控制多少次后(也就是延时多少后)才真正返回
BUSY;
回调函数返回非0,数据库会重试当前操作,返回0则当前操作返回SQLITE_BUSY;
int sqlite3_busy_timeout(sqlite3*, int ms);
不注册此函数时默认超时等待为0,当ms<=0时,清除busy handle,申请不到锁直接返回;
定义一个毫秒数,当未到达该毫秒数时,sqlite会sleep并重试当前操作,
如果超过ms毫秒,仍然申请不到需要的锁,当前操作返回SQLITE_BUSY;
很多人用这个函数没有成功,其实只要你仔细查看sqlite的源码就会发现,
这个函数实际上注册了一个默认的sqlite3_busy_handler(sqliteDefaultBusyCallback),而这个回调函数在你的编译
环境下可能使得第二个ms参数必需要大于1000且是他的整数倍才有意义,由于此默认callback函数延时较大,建议自己写回
调函数然后用slite3_busy_handler注册,这样就可以自己用自己的延时函数或方法进行处理了.
附:===================================================================
static int sqliteDefaultBusyCallback(
void *ptr, /* Database connection */
int count /* Number of times table has been busy */
)
{
#if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP)
static const u8 delays[] =
{ 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 };
static const u8 totals[] =
{ 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 };
# define NDELAY (sizeof(delays)/sizeof(delays[0]))
sqlite3 *db = (sqlite3 *)ptr;
int timeout = db->busyTimeout;
int delay, prior;
assert( count>=0 );
if( count < NDELAY ){
delay = delays[count];
prior = totals[count];
}else{
delay = delays[NDELAY-1];
prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));
}
if( prior + delay > timeout ){
delay = timeout - prior;
if( delay<=0 ) return 0;
}
sqlite3OsSleep(db->pVfs, delay*1000);
return 1;
#else
sqlite3 *db = (sqlite3 *)ptr;
int timeout = ((sqlite3 *)ptr)->busyTimeout;
if( (count+1)*1000 > timeout ){
return 0;//1000>timeout,so timeout must bigger than 1000
}
sqlite3OsSleep(db->pVfs, 1000000);//1000ms
return 1;
#endif
}
int sqlite3_busy_timeout(sqlite3 *db, int ms){
if( ms>0 ){
db->busyTimeout = ms;
sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);
}else{13-11-27 sqlite遇到database is locked问题的完美解决
www.360doc.com/content/10/1214/12/87000_77984300.shtml 2/2
sqlite3_busy_handler(db, 0, 0);
}
return SQLITE_OK;
}
3、解决方法二
加上一个循环判断。
while( 1 )
{
if( SQLITE_OK != sqlite3_exec( myconn, sql, 0, 0, &m_sqlerr_msg) )
{
if( strstr(m_sqlerr_msg, "database is locked") )
{
sleep(1);
continue;
}
break;
}
}
4、解决方法三
用信号量做PV操作
sem_p(semid,0);
sqlite3_exec( myconn, sql, 0, 0, &m_sqlerr_msg);
sem_v(semid,0);
转http://www.360doc.com/content/10/1214/12/87000_77984300.shtml
sqlite遇到database is locked问题的完美解决的更多相关文章
- dpkg: error: dpkg status database is locked by another process 解决方法
使用dpkg -i/apt命令安装,报错: ------------------------------------------------------------- dpkg: error: dpk ...
- SVN报错:sqlite[S5]:database is locked
昨天下午修改几个冲突的jar包后提交svn后报错,接下来svn操作就失灵了,无论是clean up还是revert还是release lock都无济于事.解决办法: 首先下载sqlite3,我的是64 ...
- 【转】SQLite提示database disk image is malformed的解决方法
SQLite有一个很严重的缺点就是不提供Repair命令. 导致死亡提示database disk image is malformed 它的产生有很多种可能,比如,磁盘空间不足,还有就是写入数据过程 ...
- SQLITE报错database is locked的解决办法
用firedac连接SQLITE数据库,空间tdbedit绑定字段name,如下语句修改其值时报错. procedure TForm1.Button3Click(Sender: TObject);be ...
- 使用FMDB多线程访问数据库,及database is locked的问题
每日更新关注:http://weibo.com/hanjunqiang 新浪微博 今天终于解决了多线程同时访问数据库时,报数据库锁定的问题,错误信息是: Unknown error finalizi ...
- 解决SQLite database is locked
前些时候,同事在站点服务端使用SQlite存储一些临时数据,但是在多人并发的时候Sqlite会抛出异常:The database file is locked , database is locked ...
- sqlite 报错:database is locked
在sqlite批量添加数据时,报错:database is locked. 解决办法:将db路径由相对路径设置为绝对路径.
- sqlite:多线程操作数据库“database is locked”解决方法(二)
上一篇博客<sqlite:多线程操作数据库“database is locked”解决方法>通过注册延时函数的方法来处理数据库被锁的问题.此方法固然能解决问题,但是在多个线程向数据库写入大 ...
- sqlite: Error Code : 5 (SQLITE_BUSY) (database is locked (code 5): , while compiling: PRAGMA journal_mode)
今天遇到了一个很奇怪的问题,登录完成后,程序会莫名crash, 报了下面的错误: sqlite: Error Code : (SQLITE_BUSY) (database is locked (cod ...
随机推荐
- PHPstorm最常用的快捷键,提高开发效率
PHPstorm最常用的快捷键,提高开发效率 •ctrl+b 跳到变量申明处 •Ctrl + E 打开最近文件 •Ctrl + R 替换. •Ctrl + D 复制粘贴.将当前行或者选择的内容复制粘贴 ...
- 发现linux shell中$0,$?,$!等的特殊用法
记录下linux shell下的特殊用法及参数的说明 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行的命令的结束代 ...
- lftp mirror 上传目录
1. lftp的确很强大, 要学习一下. sudo yum install lftp (测试了一下,ftp软件才92K,lftp有2.3M) 2. lftp mirror 能上 ...
- ubuntu开机自动启动xampp/lampp的两种方法
方法一: sudo ln -s /opt/lampp/lampp /etc/init.d/lampp sudo update-rc.d -f lampp defaults 方法二: 1. 在/etc ...
- oracle tnsnames.ora文件用法说明
oracle tnsnames.ora文件用法说明 CreationTime--2018年8月10日08点32分 Author:Marydon 1.用途 oracle客户端所需要的一个文件,通过该 ...
- KNOCKOUTJS DOCUMENTATION-绑定(BINDINGS)-自定义绑定
除了ko内建的绑定,还可以自定义绑定,灵活地封装复杂的行为使之可重用. 自定义绑定 注册自定义绑定 向 ko.bindingHandles添加一个子属性来注册一个绑定. ko.bindingHandl ...
- pat1040:有几个PAT
https://www.patest.cn/contests/pat-b-practise/1040 #include "stdio.h" int main() { int p = ...
- ORACLE 11G 利用泠备份恢复standby库
利用泠备份恢复standby数据库 開始使用泠备份进行db恢复 2.1,停止掉standby库 SQL> shutdown immediate; Database closed. Databas ...
- JavaScript中的闭包(closure)
闭包的特性 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收 闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露,主要用于私有的方法和变 ...
- PHP-VC9/VC6 TS/NTS等版本之间的区别
PHP的更新升级是越来越快了,PHP 5.2 版本已经更新到5.2.17不再更新, 5.3版本的更新到了5.3.8,PHP 5.4马上就要发布,甚至PHP6.0也在开发中.有这么多版本供我们选择,真是 ...