SQLite指南(6)-处理database is locked的方法

30 篇文章 0 订阅
16 篇文章 0 订阅
解决方法有:
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注册,这样就可以自己用自己的延时函数或方法进行处理了.

Java代码   收藏代码
  1. 附:===================================================================  
  2. static int sqliteDefaultBusyCallback(  
  3.  void *ptr,               /* Database connection */  
  4.  int count                /* Number of times table has been busy */  
  5. )  
  6. {  
  7. #if SQLITE_OS_WIN || (defined(HAVE_USLEEP) && HAVE_USLEEP)  
  8.   static const u8 delays[] =  
  9.      { 1251015202525,  25,  50,  50100 };  
  10.   static const u8 totals[] =  
  11.      { 013,  818335378103128178228 };  
  12. # define NDELAY (sizeof(delays)/sizeof(delays[0]))  
  13.   sqlite3 *db = (sqlite3 *)ptr;  
  14.   int timeout = db->busyTimeout;  
  15.   int delay, prior;  
  16.   assert( count>=0 );  
  17.   if( count < NDELAY ){  
  18.     delay = delays[count];  
  19.     prior = totals[count];  
  20.   }else{  
  21.     delay = delays[NDELAY-1];  
  22.     prior = totals[NDELAY-1] + delay*(count-(NDELAY-1));  
  23.   }  
  24.   if( prior + delay > timeout ){  
  25.     delay = timeout - prior;  
  26.     if( delay<=0 ) return 0;  
  27.   }  
  28.   sqlite3OsSleep(db->pVfs, delay*1000);  
  29.   return 1;  
  30. #else  
  31.   sqlite3 *db = (sqlite3 *)ptr;  
  32.   int timeout = ((sqlite3 *)ptr)->busyTimeout;  
  33.   if( (count+1)*1000 > timeout ){  
  34.     return 0;//1000>timeout,so timeout must bigger than 1000  
  35.   }  
  36.   sqlite3OsSleep(db->pVfs, 1000000);//1000ms  
  37.   return 1;  
  38. #endif  
  39. }  
  40.    
  41. int sqlite3_busy_timeout(sqlite3 *db, int ms){  
  42.   if( ms>0 ){  
  43.     db->busyTimeout = ms;  
  44.     sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db);  
  45.   }else{  
  46.     sqlite3_busy_handler(db, 00);  
  47.   }  
  48.   return SQLITE_OK;  
  49. }  

3、解决方法二
加上一个循环判断。
Java代码   收藏代码
  1. while1 )  
  2. {  
  3.     if( SQLITE_OK != sqlite3_exec( myconn, sql, 00, &m_sqlerr_msg) )  
  4.     {  
  5.         if( strstr(m_sqlerr_msg, "database is locked") )  
  6.         {  
  7.             sleep(1);  
  8.             continue;  
  9.         }  
  10.         break;  
  11.     }  
  12. }  

4、解决方法三
用信号量做PV操作
sem_p(semid,0);
sqlite3_exec( myconn, sql, 0, 0, &m_sqlerr_msg);
sem_v(semid,0);

上述4个方法是从别处转来。
还有一个方法,是对几个关键函数重新wrap,基本原理是,出现locked错误,sleep一段时间,再重新执行。第3个方法,实际上并不怎么严密。
<script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iihero

谢谢打赏,不断前行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值