標籤:
在我眼裡,MySQL和Oracle是這樣的
而SQLite在是這樣的
所以這麼萌的資料庫,我真的應該多瞭解她的。
簡介
SQLite,是一款輕型的資料庫,是遵守ACID的關係型資料庫管理系統。它的設計目標是嵌入式的,目前Android和iOS的裝置內建的都是SQLite資料庫。
SQLite雖然嬌小,但也支援事務和多數的SQL92標準。
主要特點
1. Zero-Configuration 無需安裝和管理配置。
2. Serverless 無需伺服器支援。
3. Single Database File 資料檔案儲存在一個單一的磁碟檔案。
4. Stable Cross-Platform Database File 資料庫檔案格式跨平台,無論是大小端,或者是32bit或64bit機器都沒有關係
5. Compact 完整特性的SQLite編譯出來在500KiB左右,裁剪特性甚至可以得到低於300KiB的庫(目前的版本3.8.11.1)。
6. Manifest typing 可以聲明資料庫欄位類型,但是欄位儲存的類型實際的儲存類型和實際值相關,單獨的一個欄位可能包含不同儲存類的值。
7. Variable-length records 可變長度記錄,例如你儲存一個字元到VARCHAR(100) 的列,實際需要的儲存空間一個字元加一個位元組的儲存空間。
8. SQL statements compile into virtual machine code SQL語句會被編譯成虛擬機器代碼,這種虛擬機器代碼直白可讀,便於調試。
9. Public domain 完全開源。
10. SQL language extensions
主要缺點
1. SQLite 只提供資料庫級的鎖定,所以不支援高並發。
2. 不支援預存程序。
3. SQLite 沒有使用者帳戶概念,而是根據檔案系統確定所有資料庫的許可權。這會使強制執行儲存配額發生困難,強制執行使用者許可變得不可能。
如果只在行動裝置使用SQLite,那麼他的優點足夠好,並且缺點不明顯,所以大叔MySQL走開。SQLite妹妹快過來╭(╯3╰)╮。
事務與鎖( < 3.7.0)
SQLite的事務和鎖是很重要的概念。
鎖
SQLite有5個不同的鎖狀態
1. UNLOCKED(未加鎖)
2. SHARED(共用)
3. RESERVED(保留)
4. PENDING(未決)
5. EXCLUSIVE(排它)
SQLite有一個加鎖表,記錄資料庫連接的鎖狀態。每個資料庫連接在同一時刻只能處於其中一個鎖狀態。每種狀態(UNLOCKED)都有一種鎖與之對應。
讀
資料庫連接最初處於UNLOCKED狀態,在此狀態下,串連還沒有存取資料庫。當串連到了一個資料庫,甚至已經用BEGIN開始了一個事務時,串連都還處於UNLOCKED狀態。為了能夠從資料庫中讀取資料,串連必須必須進入SHARED狀態,也就是說首先要獲得一個SHARED鎖。多個串連可以同時獲得並保持共用鎖定,也就是說多個串連可以同時從同一個資料庫中讀資料,SQLite是支援並發讀取資料的。
寫
一個串連想要寫資料庫,它必須首先獲得一個RESERVED鎖。一個資料庫上同時只能有一個RESERVED鎖,保留鎖可以與共用鎖定共存,RESERVED鎖即不阻止其它擁有SHARED鎖的串連繼續讀資料庫,也不阻止其它串連獲得新的SHARED鎖。 一旦一個串連獲得了RESERVED鎖,它就可以將資料寫入緩衝區,而不是實際地寫到磁碟。 當串連想要提交修改(或事務)時,需要獲得PENDING鎖,之後串連就不能再獲得新的SHARED鎖了,但已經擁有SHARED鎖的串連仍然可以繼續正常讀資料庫。當所有其它SHARED鎖都被釋放時,擁有PENDING鎖的串連就可以將其鎖提升至EXCLUSIVE鎖,此時就可以將以前對緩衝區所做的修改寫到資料庫檔案。所以SQLite是不支援並發寫的。
事務
SQLite有三種不同的事務
1. DEFERRED(延遲)
2. MMEDIATE(立即)
3. EXCLUSIVE(排它)
事務類型在BEGIN命令中指定:
DEFERRED
一個DEFERRED事務不擷取任何鎖(直到它需要鎖的時候),BEGIN語句本身也不會做什麼事情——它開始於UNLOCK狀態。預設情況下就是這樣的,如果僅僅用BEGIN開始一個事務,那麼事務就是DEFERRED的,同時它不會擷取任何鎖;當對資料庫進行第一次讀操作時,它會擷取SHARED鎖;同樣,當進行第一次寫操作時,它會擷取RESERVED鎖。
MMEDIATE
由BEGIN開始的IMMEDIATE事務會嘗試擷取RESERVED鎖。如果成功,BEGIN IMMEDIATE保證沒有別的串連可以寫資料庫。但是,別的串連可以對資料庫進行讀操作;但是,RESERVED鎖會阻止其它串連的BEGIN IMMEDIATE或者BEGIN EXCLUSIVE命令,當其它串連執行上述命令時,會返回SQLITE_BUSY錯誤。這時你就可以對資料庫進行修改操作了,但是你還不能提交,當你COMMIT時,會返回SQLITE_BUSY錯誤,這意味著還有其它的讀事務沒有完成,得等它們執行完後才能提交事務。
EXCLUSIVE
EXCLUSIVE事務會試著擷取對資料庫的EXCLUSIVE鎖。這與IMMEDIATE類似,但是一旦成功,EXCLUSIVE事務保證沒有其它的串連,所以就可對資料庫進行讀寫操作了。
死結
如果兩個以BEGIN DEFERRED開始事務的串連都處於SHARED狀態,並且都在等待對方結束SHARED從而進入RESERVED的話,就會進入死結狀態。所以BEGIN DEFERRED開始的事務是有可能產生死結的.
Write-Ahead Logging ( >=3.7.0 )
SQLite 3.7.0之前是不支援寫的時候讀得。為了能夠讀得時候寫,引入了Write-Ahead Logging(WAL)機制,這樣可以支援一個寫和多個讀並發。
在引入WAL機制之前,SQLite使用rollback journal機制實現原子事務。
rollback journal機制的原理是:在修改資料庫檔案中的資料之前,先將修改所在分頁中的資料備份在另外一個地方,然後才將修改寫入到資料庫檔案中;如果事務失敗,則將備份資料拷貝回來,撤銷修改;如果事務成功,則刪除備份資料,提交修改。
WAL機制的原理是:修改並不直接寫入到資料庫檔案中,而是寫入到另外一個稱為WAL的檔案中;如果事務失敗,WAL中的記錄會被忽略,撤銷修改;如果事務成功,它將在隨後的某個時間被寫回到資料庫檔案中,提交修改。
同步WAL檔案和資料庫檔案的行為被稱為checkpoint(檢查點),它由SQLite自動執行,預設是在WAL檔案積累到1000頁修改的時候;當然,在適當的時候,也可以手動執行checkpoint,SQLite提供了相關的介面。執行checkpoint之後,WAL檔案會被清空。
在讀的時候,SQLite將在WAL檔案中搜尋,找到最後一個寫入點,記住它,並忽略在此之後的寫入點(這保證了讀寫和讀讀可以並存執行);隨後,它確定所要讀的資料所在頁是否在WAL檔案中,如果在,則讀WAL檔案中的資料,如果不在,則直接讀資料庫檔案中的資料。
在寫的時候,SQLite將之寫入到WAL檔案中即可,但是必須保證獨佔寫入,因此寫寫之間不能並存執行。
WAL在實現的過程中,使用了共用記憶體技術,因此,所有的讀寫進程必須在同一個機器上,否則,無法保證資料一致性。
優點
1. 讀和寫可以完全地並發執行,不會互相阻塞(但是寫之間仍然不能並發)。
2. WAL在大多數情況下,擁有更好的效能(因為無需每次寫入時都要寫兩個檔案)。
3. 磁碟I/O行為更容易被預測
缺點
1. 訪問資料庫的所有程式必須在同一主機上,且支援共用記憶體技術。
2. 每個資料庫現在對應3個檔案:.db,-wal,-shm。
3. 當寫入資料達到GB級的時候,資料庫效能將下降。
4. 3.7.0之前的SQLite無法識別啟用了WAL機制的資料庫檔案。
5. WAL引入的相容性問題。在啟用了WAL之後,資料庫檔案格式的版本號碼由1升級到了2,因此,3.7.0之前的SQLite無法識別啟用了WAL機制的資料庫檔案。禁用WAL會使資料庫檔案格式的版本號碼恢複到1,從而可以被SQLite 3.7.0之前的版本識別。
6. WAL引入的效能問題。在一般情況下,WAL會提高SQLite的事務效能;但是在某些極端情況下,卻會導致SQLite事務效能的下降。
①在事務執行時間較長或者要修改的資料量達到GB級的時候,WAL檔案會被佔用,它會暫時阻止checkpoint的執行(checkpoint會清空WAL檔案),這將導致WAL檔案變得很大,增加定址時間,最終導致讀寫效能的下降。
②當checkpoint執行的時候,會降低當時的讀寫效能,因此,WAL可能會導致周期性的效能下降
原文連結:http://www.jointforce.com/jfperiodical/article/997?f=jf_tg_bky
原文空之境界
SQLite這麼嬌小可愛,不多瞭解點都不行啊