这两天在项目中用大强度大频率的方法测试时遇到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问题的完美解决的更多相关文章

  1. dpkg: error: dpkg status database is locked by another process 解决方法

    使用dpkg -i/apt命令安装,报错: ------------------------------------------------------------- dpkg: error: dpk ...

  2. SVN报错:sqlite[S5]:database is locked

    昨天下午修改几个冲突的jar包后提交svn后报错,接下来svn操作就失灵了,无论是clean up还是revert还是release lock都无济于事.解决办法: 首先下载sqlite3,我的是64 ...

  3. 【转】SQLite提示database disk image is malformed的解决方法

    SQLite有一个很严重的缺点就是不提供Repair命令. 导致死亡提示database disk image is malformed 它的产生有很多种可能,比如,磁盘空间不足,还有就是写入数据过程 ...

  4. SQLITE报错database is locked的解决办法

    用firedac连接SQLITE数据库,空间tdbedit绑定字段name,如下语句修改其值时报错. procedure TForm1.Button3Click(Sender: TObject);be ...

  5. 使用FMDB多线程访问数据库,及database is locked的问题

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 今天终于解决了多线程同时访问数据库时,报数据库锁定的问题,错误信息是: Unknown error finalizi ...

  6. 解决SQLite database is locked

    前些时候,同事在站点服务端使用SQlite存储一些临时数据,但是在多人并发的时候Sqlite会抛出异常:The database file is locked , database is locked ...

  7. sqlite 报错:database is locked

    在sqlite批量添加数据时,报错:database is locked. 解决办法:将db路径由相对路径设置为绝对路径.

  8. sqlite:多线程操作数据库“database is locked”解决方法(二)

    上一篇博客<sqlite:多线程操作数据库“database is locked”解决方法>通过注册延时函数的方法来处理数据库被锁的问题.此方法固然能解决问题,但是在多个线程向数据库写入大 ...

  9. 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 ...

随机推荐

  1. 服务名无效。请键入 NET HELPMSG 2185 以获得更多的帮助。

    1:关闭MySQL服务的时候出现“服务名无效.请键入 NET HELPMSG 2185 以获得更多的帮助.”错误. 2:查看服务名称 3:重新关闭服务 4:管理员运行控制台后重新执行 成功停掉了.

  2. MSSQL语句批量替换表中某列字段内容的某个字符

    UPdate 表 Set 字段名=REPLACE(字段名,'查找目标字符','要替换的字符') 比如:在Products表中把字段CharCode中含有ch-的字符全部替换为dw- UPDATE Pr ...

  3. [Unity-1] Unity简单介绍

    Unity是一套包含图形.声音.物理等功能的游戏引擎,提供了一个强大的关卡编辑器.支持大部分主流3D软件格式,使用C#或者JavaScript等高级语言实现脚本功能.使开发人员无需了解底层复杂技术,高 ...

  4. HDOJ 4699 Editor 栈 模拟

    用两个栈模拟: Editor Time Limit: 3000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  5. 在notepad++中运行python代码

    #在notepad++中运行python代码 ''' 1.安装插件pyNPP, 2.允许插件pyNPP中的第一个和第二个选项即可,如果代码过少代码执行一闪而过,可能无法看到,可加入少量sleep时间即 ...

  6. 全球免费知名DNS服务器

    全球免费知名DNS服务器 jalone 2013-06-18 14:25:46 最近老是发表DNS相关文章,今天继续说DNS,国内75%以上的家用宽带路由器存在严重的安全隐患:用户浏览网页的时候其DN ...

  7. nginx 配置web 虚拟文件夹 而且codeIgniter,thinkphp 重定向url 地址

    nginx 配置虚拟文件夹而且url 重定向 server { #侦听80port listen 8090; #定义使用www.xx.com訪问 server_name 127.0.0.1; #设定本 ...

  8. 判断是否为SIM卡联系人

    判断是否为SIM卡联系人 在AsyncQueryContacts类中. private List<TxrjAccount> accounts = new ArrayList<Txrj ...

  9. kubernetes中使用NFS创建pv_pvc

    Persistent Volume(持久化卷)简称PV, 是一个K8S资源对象,我们可以单独创建一个PV, 它不和Pod直接发生关系, 而是通过 Persistent Volume Claim, 简称 ...

  10. webdriver API study

    This chapter cover all the interfaces of Selenium WebDriver. Recommended Import Style The API defini ...