SQLite指南(6)-处理database is locked的方法
SQLite指南(6)-处理database is locked的方法
博客分类:
DB2|PostgreSQL|SQLite|Others
解决方法有:
1。使用进程或线程间的同步机制以避免同时操作;如用信号量,互斥锁等(pthread_mutex_lockpthread_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,申请不到锁直接返回;
定义一个毫秒数,当未到达该毫秒数时,sqlitesleep并重试当前操作,
如果超过ms毫秒,仍然申请不到需要的锁,当前操作返回SQLITE_BUSY;
很多人用这个函数没有成功,其实只要你仔细查看sqlite的源码就会发现,
这个函数实际上注册了一个默认的sqlite3_busy_handlersqliteDefaultBusyCallback),而这个回调函数在你的编译环境下可能使得第二个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.      { 1251015202525255050100 };   
10.   static const u8 totals[] =   
11.      { 013818335378103128178228 };   
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.
:===================================================================
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{
    sqlite3_busy_handler(db, 0, 0);
  }
  return SQLITE_OK;
}

3、解决方法二
加上一个循环判断。
Java代码
1. while( 1 )   
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.
while( 1 )
{
    if( SQLITE_OK != sqlite3_exec( myconn, sql, 0, 0, &m_sqlerr_msg) )
    {
        if( strstr(m_sqlerr_msg, "database is locked") )

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。