SQLite busy handler
2018-06-17 19:57:47来源:未知 阅读 ()
SQLite doesn't support high concurrency. In case of a lot of concurrent access from multi-process or multi-thread, calling a SQLite r/w function is prone to hit the case that the database is locked by another process or thread. The default behavior is that the SQLite r/w function return SQLITE_BUSY immediately, and the caller should retry the call later.
Below is an example function. When the SQLite function returns SQLITE_BUSY, the caller sleep one second then retry. The sleep is required to optimize the CPU utilization, without the sleep, the CPU will be occupied by a lot of retries.
bool Execute(const string& sql) { char* errmsg = NULL; while (true) { int status = sqlite3_exec(db_, sql.c_str(), NULL, NULL, &errmsg); if (status == SQLITE_OK) { return true; } else if (status == SQLITE_BUSY) { ++total_busycount; cerr << "Thread " << threadindex_ << ": failed to execute " << sql << " (" << errmsg << ")\n"; sqlite3_free(errmsg); sleep(1); } else { cerr << "Thread " << threadindex_ << ": failed to execute " << sql << " (" << errmsg << ")\n"; sqlite3_free(errmsg); return false; } } return false; }
In fact, the caller doesn't need to sleep explicitly, calling sqlite3_busy_timeout before SQLite r/w functions will make SQLite automaticlly insert sleep between two sequential calls of a r/w function. It's safe to set a big timeout value. SQLite splits the big timeout value into many small timeout values. With the optimization, if the lock is available while the caller is waiting, the caller won't need to wait to timeout. See below code,
1452 static int sqliteDefaultBusyCallback( 1453 void *ptr, /* Database connection */ 1454 int count /* Number of times table has been busy */ 1455 ){ 1456 #if SQLITE_OS_WIN || HAVE_USLEEP 1457 static const u8 delays[] = 1458 { 1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 }; 1459 static const u8 totals[] = 1460 { 0, 1, 3, 8, 18, 33, 53, 78, 103, 128, 178, 228 }; 1461 # define NDELAY ArraySize(delays) 1462 sqlite3 *db = (sqlite3 *)ptr; 1463 int timeout = db->busyTimeout; 1464 int delay, prior; 1465 1466 assert( count>=0 ); 1467 if( count < NDELAY ){ 1468 delay = delays[count]; 1469 prior = totals[count]; 1470 }else{ 1471 delay = delays[NDELAY-1]; 1472 prior = totals[NDELAY-1] + delay*(count-(NDELAY-1)); 1473 } 1474 if( prior + delay > timeout ){ 1475 delay = timeout - prior; 1476 if( delay<=0 ) return 0; 1477 } 1478 sqlite3OsSleep(db->pVfs, delay*1000); 1479 return 1; 1480 #else 1481 sqlite3 *db = (sqlite3 *)ptr; 1482 int timeout = ((sqlite3 *)ptr)->busyTimeout; 1483 if( (count+1)*1000 > timeout ){ 1484 return 0; 1485 } 1486 sqlite3OsSleep(db->pVfs, 1000000); 1487 return 1; 1488 #endif 1489 }
Another alternative is set a busy hander by calling sqlite3_busy_handler. If the busy callback returns 0, then no additional attempts are made to access the database and SQLITE_BUSY is returned to the application. If the callback returns non-zero, then another attempt is made to access the database and the cycle repeats.
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- Python操作SQLLite(基本操作) 2019-05-24
- Python:logging.NullHandler 的使用 2018-11-29
- PyQt5--EventHandler 2018-09-18
- Python 使用数据库(SQLite) 2018-07-28
- 数据库——SQLite---->Java篇 2018-06-22
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash