Linux下sqlite3多執行緒和序列模式
sqlite3支援三種模式:單執行緒模式,多執行緒模式和序列模式。
模式可在編譯,啟動時或執行時設定,一般來講,啟動時的設定會覆蓋編譯時的設定,執行時則會覆蓋啟動時或編譯時的設定。但是一旦單執行緒模式被設定之後就不能再被覆蓋了。
編譯時可通過SQLITE_THREADSAFE設定模式。sqlite3標準 發行版本預設設定為SQLITE_THREADSAFE=1, 即序列模式。SQLITE_THREADSAFE=2為多執行緒模式,SQLITE_THREADSAFE=0為單執行緒模式,當設定為0時,即使初始化或執行時設定為其他模式,也會保持單執行緒模式。
啟動時是指在sqlite3在初始化之前呼叫sqlite3_config()函式設定,引數為SQLITE_CONFIG_SINGLETHREAD,SQLITE_CONFIG_MULTITHREAD或SQLITE_CONFIG_SERIALIZED。
sqlite3初始化指的是呼叫sqlite3_initalize(),該函式會在呼叫sqlite3_open_v2()時呼叫。執行時也就是程式第一次(僅第一次呼叫有效)呼叫該函式建立資料庫連線時,通過設定第三個引數為設定不同模式,SQLITE_OPEN_NOMUTEX為多執行緒模式,SQLITE_OPEN_FULLMUTEX為序列模式。
序列模式
序列模式支援多執行緒操作,但是必須統一使用一個全域性的資料庫連線,這一點非常重要。序列模式會開啟sqlite3所有的鎖,在同一時刻保證只有一個執行緒能訪問。這裡可以理解為只有一條指向資料庫的連線,多個執行緒的請求將會在該連線上序列傳輸。
多執行緒模式
多執行緒模式支援執行緒併發操作,但也有例外,因為在該模式下,sqlite3打開了bCoreMutex鎖,關閉了bFullMutex鎖,也就禁止了多個執行緒併發使用同一個資料庫連線和perpared statement, perpared statement可以簡單的使用訊號量進行互斥。
使用多執行緒模式,除了需要設定模式外,還必須在執行資料庫操作前呼叫sqlite3_busy_handler()或sqlite3_busy_timeout() 。這兩個函式會判斷sqlite是否處於SQLITE_BUSY狀態,是的話將進行sleep等待。區別在於sqlite3_busy_handler()需要自己實現等待的處理,而sqlite3_busy_timeout()實際上是呼叫了sqlite3_busy_handler()並使用一個預設的等待處理函式。
sqlite3_busy_timeout()通過指定最大超時時間進行等待。根據sqlite3_busy_timeout()原始碼,需要注意,如果系統未定義HAVE_USLEEP或定定義為false,則超時時間必須指定為大於1000且是它的整數倍。
無論有無定義,使用sqlite3_busy_timeout()的等待時間都是該函式的演算法實現,所以如果需要完全按照自己的需求決定等待時間,可以使用sqlite3_busy_handler(),該函式需要自己實現等待處理函式,處理函式中即可指定等待時間。sqlite3_busy_timeout() 原始碼:
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;
}
Exmaple
// 判斷編譯時模式,設定啟動時模式為多執行緒模式
int mode = sqlite3_threadsafe();
if (mode == 0) {
AIO_LOG_W("SQLite database is not compiled to be threadsafe");
return AIO_ERR;
}
int ret = sqlite3_config(SQLITE_CONFIG_MULTITHREAD);
if (ret != SQLITE_OK) {
AIO_LOG_E("setting sqlite thread safe mode to multithread failed: %d", ret);
return AIO_ERR;
}
... ...
// 設定SQLITE_BUSY 處理,使用sqlite3_busy_timeout()
#define SQLITE_EXE(db, sql, callback, ptr, msg) \
{ \
rc = sqlite3_busy_timeout(db, 10 * MSEC_PER_SEC); \
if (rc != SQLITE_OK) { \
AIO_LOG_E("SQL error: %d, file: %s. func: %s, line: %d.\n", \
rc, __FILE__, __func__, __LINE__); \
} \
rc = sqlite3_exec(db, sql, callback, ptr, &msg); \
if (rc != SQLITE_OK) { \
AIO_LOG_E("SQL error: %s, file: %s. func: %s, line: %d.\n", \
msg, __FILE__, __func__, __LINE__); \
sqlite3_free(msg); \
} \
}
// 設定SQLITE_BUSY 處理,使用sqlite3_busy_handler()
static int cb_sql_busy(void *ptr, int count)
{
int timeout = *((int *)ptr);
(void)usleep(timeout);
return 1;
}
static int sql_busy_check(sqlite3 *db, int ms)
{
if( ms > 0 )
sqlite3_busy_handler(db, cb_sql_busy, (void*)&ms);
else
sqlite3_busy_handler(db, 0, 0);
return SQLITE_OK;
}
int my_sqlite_exe(...) {
rc = sql_busy_check(db, 100);
... ...
rc = sqlite3_exec(db, sql, NULL, NULL, &msg);
... ...
}
相關推薦
Linux下sqlite3多執行緒和序列模式
sqlite3支援三種模式:單執行緒模式,多執行緒模式和序列模式。 模式可在編譯,啟動時或執行時設定,一般來講,啟動時的設定會覆蓋編譯時的設定,執行時則會覆蓋啟動時或編譯時的設定。但是一旦單執行緒模式被設定之後就不能再被覆蓋了。 編譯時可通過SQLITE_T
Linux下c++多執行緒和互斥鎖
一、多執行緒 多執行緒使用的是pthread庫,寫程式的時候需要引入標頭檔案pthread.h, g++編譯的時候需要加上該庫的依賴“-lpthread”。 1 先看程式便於理解,程式碼下面有對註釋的解釋。下面的程式碼含義是建立兩個執行緒,一個執行緒去計算某
linux下用多執行緒實現socket伺服器和客戶端的非同步通訊
前面介紹了用select函式來實現socket的非同步收發資料,但是select函式也有一些缺陷,要使socket能持續地通訊,select必須不停地檢測,這樣程序就會一直阻塞在這裡,限制了功能的擴充套件,這裡我們用多執行緒的方式,另建立兩個執行緒用來發送/接收
linux下的多執行緒/多程序同步/通訊機制
while (1) { //這個mutex主要是用來保證pthread_cond_wait的併發性 pthread_mutex_lock(&mtx); while (head == NULL) {
Linux下的多執行緒程式設計二(執行緒的同步與互斥)
一、什麼叫做執行緒的同步與互斥?為什麼需要同步與互斥? 1、同步與互斥 互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。 同步:是指在互斥的基礎上(大多數情況),通過其它機制
樹莓派3B Linux下C++多執行緒程式設計
下面的程式碼手動建立了兩個執行緒,一個執行緒是讀取串列埠的資料,另一個執行緒是通過UDP來讀取網路通訊收到的資料。加上main函式的執行緒,一共三個執行緒。 先簡單講一下多執行緒的建立, pthread_t serial; int ser =
linux下核心多執行緒的簡單實現
#include<linux/init.h> #include<linux/module.h> #include<linux/kernel.h> #include<linux/delay.h> #include<linux/wait.h> #incl
Linux下的多執行緒程式設計
我們編譯此程式: gcc example1.c -lpthread -o example1 執行example1,我們得到如下結果: This is the main process. This is a pthread. This is the main process. This is the ma
Solaris10 下的多執行緒和Mysql多執行緒連線
1. Solairs下的多執行緒 執行緒分成兩種,一種是POSIX格式的(使用 pthread.h),一種是Solairs格式的(thread.h),建議使用 POSIX格式。 int pthread_create(pthread_t *restrict th
day24總結_多執行緒和設計模式
1、多執行緒 ①、JDK5以後的針對執行緒的鎖定操作和釋放操作 // 定義鎖物件 private Lock lock = new ReentrantLock(); // 加鎖 lock.lock(); // 釋放鎖 lock.unlock(); ②、死鎖問題的描述和程式碼體現 *死鎖:兩個或
Linux 多執行緒和多程序的區別(小結)
最近學習Linux,看到“hairetz的專欄”的帖子不錯,特轉來大家一起學習。 很想寫點關於多程序和多執行緒的東西,我確實很愛他們。但是每每想動手寫點關於他們的東西,卻總是求全心理作祟,始終動不了手。 今天終於下了決心,寫點東西,以後可以再修修補補也無妨。一.為何需要多程序(或者多執行緒),為何需
Linux作業系統下的多執行緒程式設計詳細解析----條件變數pthread_cond_t
在多執行緒程式設計下,常常出現A執行緒要等待B執行緒條件完成後再繼續進行,這裡等待方式有兩種: 1.使用鎖+輪詢 使用這種方法可以很簡單的實現,但是會有一定的效能消耗,其還有一個點要好好把握,就是一次輪詢沒有結果後相隔多久進行下一次的輪詢,間隔時間太短,消耗
多執行緒和多核下“鎖”的應用
假設這樣一種情況:有多個執行緒(或多核)需要在共享資料A滿足某一條件時,對A進行操作. 以下舉例兩種實現 Fun_1() { lock()--------------1.1 Result=Check(A)-----1.2 Unlock()------------
多核CPU和單核CPU下的多執行緒
多核CPU和單核CPU下的多執行緒 多執行緒程式設計是現代軟體技術中很重要的一個環節。要弄懂多執行緒,這就要牽涉到多程序?當然,要了解到多程序,就要涉及到作業系統。不過大家也不要緊張,聽我慢慢道來。這其中的環節其實並不複雜。 單核CPU下的多執行緒 在沒有出現多核CPU之前,我們
作業系統實驗——序列、多執行緒和執行緒池三種方式計算矩陣乘法
package cn.edu.seu.yujun.OS; /** * * @author Fish * Date:2015/4/7 */ public class WorkThread implements Runnable { private int start;//計算開始位置,以此區分工作執
【Linux】GDB除錯多執行緒和多程序以及Core檔案
GDB偵錯程式 基本概念 GDB是GNU開源組織釋出的一個強大的UNIX下的程式除錯工具。或許,各位比較喜歡那種圖形介面方式的,像VC、BCB等IDE的除錯,但如果你是在UNIX平臺下做軟體,你會發現
如何在Windows和Linux下獲取當前執行緒的ID號
Linux下獲取當前執行緒ID號函式: pthread_t pthread_self(); 返回:當前執行緒的ID號 pthread_t 資料型別的定義如下: typedef unsigned long int pthread_t; sizeof(pthread_t) =
Linux:使用多執行緒程式設計和訊息佇列,實現兩個程序之間的聊天
思路: 一個檔案:建立一個執行緒和主函式,或者建立兩個執行緒主函式呼叫(我用這種)。 建立兩個訊息佇列, 一共兩個檔案,兩個佇列,四個程序 a.c 一個程序寫(訊息型別為1) ---->>佇列 一個程序讀(訊息型別為2) b.c 一
VC6.0下建立多執行緒的方法和注意的事項
#include<stdio.h> #include <process.h> #include <stdio.h> #include <windows.h> DWORD _stdcall ThreadProc(LPVOID l
多執行緒程式設計之Linux環境下的多執行緒(一)——好文
一、Linux環境下的執行緒 相對於其他作業系統,Linux系統核心只提供了輕量級程序的支援,並未實現執行緒模型。Linux是一種“多程序單執行緒”的作業系統,Linux本身只有程序的概念,而其所謂的“執行緒”本質上在核心裡仍然是程序。 程序是資源分配的單位,同一程序中的多個執行緒共享該程序的