SQLite 是線程安全的纵东,支持多線程操作歼捏。如何開(kāi)啟呢?
1而涉, PRAGMA SQLITE_THREADSAFE=2 確保同一個(gè)時(shí)間只有一個(gè)線程操作一個(gè)數(shù)據(jù)庫(kù)
2著瓶,開(kāi)啟WAL模式:原來(lái)就是開(kāi)啟了WAL,讀寫(xiě)操作都是提交一些事物到WAL文件里面去啼县,然后定時(shí)checkpoint提交到數(shù)據(jù)庫(kù)材原,當(dāng)讀取數(shù)據(jù)的時(shí)候,會(huì)在wal里面添加一個(gè)end mark季眷,這樣讀取的時(shí)候余蟹,后面的更新和插入都和讀取沒(méi)關(guān),所以保證了讀取同步進(jìn)行子刮,效率高威酒。
https://blog.csdn.net/zearot/article/details/51039593,但是寫(xiě)寫(xiě)之間還是不能同步的Mο俊<娌!缺點(diǎn)沙郭。所以下面這個(gè)點(diǎn)
3佛呻, SQLite 提供了 Busy Retry 的方案,即發(fā)生阻塞時(shí)病线,會(huì)觸發(fā) Busy Handler吓著,此時(shí)可以讓線程休眠一段時(shí)間后,重新嘗試操作送挑。重試一定次數(shù)依然失敗后绑莺,則返回 SQLITE_BUSY 錯(cuò)誤碼。它是通過(guò)文件鎖的方式去鎖住文件惕耕,SQLITE_BUSY 通過(guò) fcntl 進(jìn)行文件鎖纺裁,防止其他進(jìn)程介入。若鎖失敗司澎,則返回 SQLITE_BUSY欺缘。
因?yàn)樗鼪](méi)有通知的機(jī)制,例如其他進(jìn)程用完這個(gè)數(shù)據(jù)庫(kù)發(fā)出通知挤安,這樣SQLite_BUSY 的文件鎖就可以成功鎖住了文件谚殊,所以它才只能通過(guò)多次嘗試的方法去鎖文件
如何對(duì)SQLite 進(jìn)行優(yōu)化?
1蛤铜,優(yōu)化點(diǎn)針對(duì)的是上面第3點(diǎn)嫩絮,由于Busy Retry的機(jī)制文件鎖沒(méi)有通知的機(jī)制丛肢,所以我們可以添加通知的機(jī)制:當(dāng)文件被鎖住沒(méi)辦法加文件鎖的時(shí)候,我們就將我們的事務(wù)加到一個(gè)FIFO的queue里面剿干,線程通過(guò)pthread_cond_wait進(jìn)入睡眠蜂怎,當(dāng)文件解鎖的時(shí)候,會(huì)通過(guò)pthread_cond_signal_thread_np 信號(hào)去喚醒這個(gè)線程置尔,這樣線程就可以對(duì)這個(gè)文件進(jìn)行鎖住去寫(xiě)文件了派敷。
2, 開(kāi)始MMAP撰洗,內(nèi)存映射篮愉,低版本sqllite沒(méi)有默認(rèn)打開(kāi)。但是對(duì)WAL還是沒(méi)有進(jìn)行MMAP操作差导,那么怎么辦呢试躏?可以減少WAL的刪除和重建,在checkpoint之后设褐,修改WAL文件頭部的參數(shù)颠蕴,這樣SQLite 識(shí)別到WAL已經(jīng)不可用就會(huì)重新從頭開(kāi)始寫(xiě)入。 有了上面兩個(gè)優(yōu)化就可以大大提升了性能助析。
3犀被,可以關(guān)閉內(nèi)存統(tǒng)計(jì),內(nèi)存統(tǒng)計(jì)是在全局變量里計(jì)算外冀,所以有頻繁的加鎖解鎖操作比較耗時(shí)
sqlite3_config(SQLITE_CONFIG_MEMSTATUS寡键, 0)