这两天在项目中用大强度大频率的方法测试时遇到sqlite报database is locked的问题,
分析下来原因是sqlite对数据库做修改操作时会做(文件)锁使得其它进程同一时间使用时会报该错误(也就是@R_749_5607@BUSY),但如果仅是多进程或多线程查询sqlite是支持的。
解决方法有:
1。使用进程或线程间的同步机制以避免同时操作;如用信号量,互斥锁等(pthread_mutex_lock,pthread_mutex_unlock),如果你的项目工程较大要求较高的话建议用此方法自行封装函数处理同步
2。使用SQLite提供的两个busy handler函数,但对于一个连接来说,只能有一个busy handle,两个函数会相互影响,设置一个的同时会清除另一个,应根据需要来选择。
intsqlite3_busy_handler(sqlite3 *,int (*)(void *,int),void *)
不注册此函数时默认回调函数为NulL,清除busy handle,申请不到锁直接返回;
函数可以定义一个回调函数,当出现数据库忙时sqlite会调用该函数进行延时并返回非0会重试本次操作,回调函数的第二个参数会被传递为此次因BUSY忙事件而调用该函数的次数,因此你完全可以自行控制多少次后(也就是延时多少后)才真正返回BUSY;
回调函数返回非0,数据库会重试当前操作,返回0则当前操作返回@R_749_5607@BUSY;
intsqlite3_busy_timeout(sqlite3*,int ms);
不注册此函数时默认超时等待为0,当ms<=0时,清除busy handle,申请不到锁直接返回;
定义一个毫秒数,当未到达该毫秒数时,sqlite会sleep并重试当前操作,
如果超过ms毫秒,仍然申请不到需要的锁,当前操作返回@R_749_5607@BUSY;
很多人用这个函数没有成功,其实只要你仔细查看sqlite的源码@R_757_10585@, 这个函数实际上注册了一个默认的sqlite3_busy_handler(sqliteDefaultBusyCallBACk),而这个回调函数在你的编译环境下可能使得第二个ms参数必需要大于1000且是他的整数倍才有意义,由于此默认callBACk函数延时较大,建议自己写回调函数然后用slite3_busy_handler注册,这样就可以自己用自己的延时函数或方法进行处理了.
附:===================================================================stati
c int sqliteDefaultBusyCall
BACk(
void *ptr,/* Database connection */
int count /*
number of times table has been busy */ )
{#if @R_749_5
607@OS_WIN || (defined(HAVE_USLEE
p) && HAVE_USLEE
p) static const u8 delays[] =
{ 1,2,5,10,15,20,25,50,100 }; static const u8 @R_752_1
0586@ls[] =
{ 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 = @R_752_1
0586@ls[count]; }else
{ delay = delays[NDELAY-1]; prior = @R_752_1
0586@ls[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,
sqliteDefaultBusyCall
BACk,(
void*)db
); }else
{ sqlite3_busy_handler(db,0
); } return @R_749_5
607@OK; }3、解决方法二加上一个循环判断。 while( 1 )
{ if( @R_749_5
607@OK
!= sqlite3_exec( myconn,sql,&m_sqlerr_msg) )
{ if( strstr(m_sqlerr_msg,"database is locked") )
{ sleep
(1); con
Tinue; } break; } } 4、解决方法三 用信号量做PV操作 sem_p(semID,0);
sqlite3_exec( myconn,&m_sqlerr_msg); sem_v(semID,0
);
@H_
450_28@
大佬总结
以上是大佬教程为你收集整理的sqlite遇到database is locked问题的完美解决全部内容,希望文章能够帮你解决sqlite遇到database is locked问题的完美解决所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。