sqlite遇到database is locked问题的完美解决

这两天在项目中用大强度大频率的方法测试时遇到sqlite报database is locked的问题,
分析下来原因是sqlite对数据库做修改操作时会做(文件)锁使得其它进程同一时间使用时会报该错误(也就是SQLITE_BUSY),但如果仅是多进程或多线程查询sqlite是支持的。
解决方法有:
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会重试本次操作,
回调函数的第二个函数会被传递为该由此次忙事件调用该函数的次数
回调函数返回非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),
而这个回调函数使得第二个参数必段要大于1000且是他的整数倍才有意义,
由于此默认callback函数延时较大,建议自己写回调函数然后用sqlite3_busy_handler注册

作者: morneve   发布时间: 2010-11-15