**於sqlite官方**上的文件:http://www.sqlite.org/lockingv3.html
sqlite3
寫資料庫
為了寫sqlite3
資料庫,程序必須先獲取
shared
鎖。當獲取
shared
鎖之後,程序需要進一步申請
reserved
鎖。reserved
鎖表示該程序會在不遠的將來執行寫資料庫操作。同一時刻只有乙個程序能夠獲取
reserved
鎖。但是其他程序此時還是可以獲取
shared
鎖來讀取資料庫中的內容
當寫資料庫的程序試圖
reserved
鎖未遂,意味著此時有另乙個程序已經獲取了
reserverd
鎖。在這種情況下,寫資料庫將會失敗,並返回
sqlite_busy
錯誤。獲取
reservered
鎖之後,寫資料庫程序將先建立乙個
rollback journal
。journal
的頭部被初始化成
sqlite
資料庫檔案的原始大小。同時該頭部也為
master journal
保留了空間,儘管該
master-journal
初始值為空。
在對db
的任何乙個
page
(資料是以
page
的形式組織的)
執行更新之前,程序需要將該
page
的原始內容寫到
rollback journal
中。被改變的
page
起初被儲存在記憶體中,並沒有寫到
disk
上。原始的資料庫還是處於未被修改的狀態,換句話說,其它程序還是能繼續讀取原始的資料。
最後,寫資料的程序準備真正更新資料庫了。更新的時機在於
memory cache
滿了需要換出,或者是程序已經準備好
commit
這次update
。在更新發生之前,寫資料庫的程序必須確保沒有其他程序正在讀資料庫,同時
rollback journal
的資料也已經安全儲存到磁碟上,以確保在更新失敗時,
rollback
能夠正確進行。以下將是更新資料庫的具體步驟:
1. 確保所有的
rollback journal
都被寫到
disk
上(而不是os的
fs中或者
disk controller
的cache
中),以防止突然掉電重啟後,資料依然可以恢復。
2. 獲取
pending
鎖,再進一步獲取該資料庫檔案上的
exclusive(排他)
鎖。如果此時該資料庫檔案上有
shared
鎖(被其他程序所占用),寫程序必須等帶直到獲取
exclusive
(排它)鎖。
3. 將
memory
中所有修改過的
page
寫到資料庫檔案中。
如果由於
memory cache
滿了導致的寫資料庫操作,寫程序自己並不知道,也不會立即
commit
。相反,寫程序可能會繼續對記憶體中的
page
作更新操作。在後續的更新被寫到資料庫檔案之前,
rollback journal
必須先被
flush
到disk
上。同時也要注意,先前因為
memory cache
滿而寫資料庫時獲取的
exclusive
(排他)鎖,將會一直保持到所有的更新都被
commit
。換句話說,一旦
memory cache
滿了,並且第一次成功寫入資料庫後,沒有任何其他程序可以訪問資料庫。(排它鎖一旦獲取,就不會降級,直到所有的更新被提交給資料庫)
當乙個寫程序準備
commit
更新時,它將執行一下操作:
4. 獲取該資料庫檔案上的排他鎖,並確保所有
memory
中的更新都正確寫到
disk
上。其邏輯由上述
1-3步驟描述
5. 將所有該資料庫檔案上的更新
flush
到disk
上。(同步過程,資料真正寫到磁碟表面才會返回)
6. 刪除
journal
檔案(如果
pragma journal mode
被設定成
truncate
或者persist
時,則相應地
truncate journal
檔案或者清空
journal
journal
檔案之前,如果出現掉電或者
crash
的情況,當下乙個程序開啟資料庫檔案時,將會發現該資料庫檔案有乙個
hot journal
檔案殘留,並會根據該
journal
檔案回滾所有的更新。當
journal
檔案被刪除後,將不會存在所謂的
hot journal
檔案,所有的更新即被持久化下來。
7. 釋放該資料庫檔案上的
exclusive
鎖和pending鎖一旦
pending
鎖被釋放,其他程序就可以讀取該資料庫檔案中的內容。在當前(
sqlite3
)的實現中,
reserved
鎖也會一同被釋放,雖然無傷大雅。將來的
sqlite
可能會提供
"chech point" sql
命令,可以用來在乙個
transaction
內,提交到當前位置的所有變化,同時保持
reserved
鎖。這樣後續的更新就能確保不會被其他的寫程序搶占。
如果乙個
transaction
涉及到多個
db檔案,提交的邏輯將會更加複雜(
1-3步驟是一樣的,從第
4步開始有所變化):
4. 確保所有的資料庫檔案都獲取到了排它鎖以及正確的
journal
檔案。5.
建立乙個
master-journal
檔案,該
master-journal
檔案的名稱為
arbitray
。(目前的實現是在
"主資料庫檔案
——main database file(
怎麼確定主資料檔案,沒有交代
)"名稱後加乙個隨機數字尾,知道該檔名沒有被使用過為止)該
master-journal
中記錄的是各個db的
journal
檔名稱。(同樣,此時要保證
master-journal
被正確flush
到disk
上)6.
將master-journal
的名稱寫到相關的各個
journal
檔案中(在建立
rollback journal
的時候,為
master journal
預留了空間)。同時
flush
各個journal
檔案到disk
上(是指真正的磁碟表面)。
7. 將資料庫檔案們的更新
flush
到磁碟表面。
8. 提交
transaction
同時,刪除
master-journal
檔案。同理如果在刪除之前,出現掉電,
crash
等情況,參考上個
session的第6
步驟9.
刪除各個
db檔案相關的
journal
檔案10.
釋放相關資料庫檔案上的
exclusive
鎖和pending
鎖寫飢餓
在sqlite2
中,如果有很多程序讀資料庫,很有可能每時每刻都有程序在讀
db。也就是說每時每刻都有程序佔據db的
shared
鎖,寫程序將沒有機會獲取
exclusive
鎖,即導致所謂的寫飢餓。
sqlite 3
通過使用
pending
鎖來解決寫飢餓的問題。
pending
鎖允許當前正在讀
db的程序完成讀操作,但是不允許新的讀操作。因此,當乙個程序準備寫
db時,它將先申請
pending
鎖,阻斷後續的讀操作。而當當前正在讀的所有程序完成讀取操作後,
shared
鎖都被釋放,從而寫程序就可以獲取
exclusive
鎖,進而可以對資料庫進行寫操作。
Sqlite3 資料庫使用
iphone本身是支援 sqlite3 資料庫的,在專案中匯入libsqlite3.dylib。並建立資料庫,在終端,建立資料庫的方式 mkdir sql 建立sql資料夾 cd sql 進入sql目錄下 sqlite3 student.sql 建立名為 student.sql的資料庫 建立表 插入...
sqlite3資料庫操作
1 開啟資料庫 1 需要制定資料庫的路徑 nsstring filepath nshomedirectory documents data.sqlite 2 建立資料庫的物件 sqlite3 qingyundb null 3 開啟命令 sqlite3 open dbfilepath utf8stri...
SQLite3資料庫操作
簡單的sqlite3語句,通過字串拼接執行資料庫操作。1.建立資料庫格式 db.execsql create table if not exists sharp id integer primary key,name varchar,level integer,high integer 其真正的有效...