SQLite學(xué)習(xí)(六)

一、數(shù)據(jù)庫鎖

SQLite 采用粗放型的鎖葵萎。當(dāng)一個(gè)連接要寫數(shù)據(jù)庫怨规,所有其它的連接被鎖住,直到寫連接結(jié)束了它的事務(wù)。 SQLite 有一個(gè)加鎖表舶得,來幫助不同的寫數(shù)據(jù)庫都能夠在最后一刻再加鎖, 以保證最大的并發(fā)性纫骑。

SQLite 使用鎖逐步上升機(jī)制九孩,為了寫數(shù)據(jù)庫,連接需要逐級(jí)地獲得排它鎖煤墙。
SQLite有5個(gè)不同的鎖狀態(tài):未加鎖(UNLOCKED)宪拥、共享(SHARED)、保留 (RESERVED)脚作、未決(PENDING)和排它(EXCLUSIVE)缔刹。

注意:每個(gè)數(shù)據(jù)庫連接在同一時(shí)刻只能處于其中一個(gè)狀態(tài)。每種狀態(tài)(未加鎖狀態(tài)除外)都有一種鎖與之對(duì)應(yīng)亿扁。

下面具體講解下各個(gè)鎖:
1灭翔、最初的狀態(tài)是未加鎖狀態(tài)辣苏,在此狀態(tài)下哄褒,連接還沒有存取數(shù)據(jù)庫。當(dāng)連接到了一個(gè)數(shù)據(jù)庫退客, 甚至已經(jīng)用 BEGIN 開始了一個(gè)事務(wù)時(shí)链嘀,連接都還處于未加鎖狀態(tài)。
2茫藏、未加鎖狀態(tài)的下一個(gè)狀態(tài)是共享狀態(tài)霹琼。為了能夠從數(shù)據(jù)庫中讀(不寫)數(shù)據(jù),連接必須首先進(jìn)入共享狀態(tài)枣申,也就是說首先要獲得一個(gè)共享鎖忠藤。多個(gè)連接可以同時(shí)獲得并保持共享鎖,也就是說多個(gè)連接可以同時(shí)從同一個(gè)數(shù)據(jù)庫中讀數(shù)據(jù)模孩。但哪怕只有一個(gè)共享鎖還沒有釋放瓜贾,也不允許任何連接寫數(shù)據(jù)庫。
3祭芦、如果一個(gè)連接想要寫數(shù)據(jù)庫,它必須首先獲得一個(gè)保留鎖胃夏。一個(gè)數(shù)據(jù)庫上同時(shí)只能有一個(gè)保留鎖昌跌。保留鎖可以與共享鎖共存,保留鎖是寫數(shù)據(jù)庫的第 1 階段答恶。保留鎖即不阻止其它擁有共享鎖的連接繼續(xù)讀數(shù)據(jù)庫,也不阻止其它連接獲得新的共享鎖污呼。
4包竹、一旦一個(gè)連接獲得了保留鎖,它就可以開始處理數(shù)據(jù)庫修改操作了苗缩,盡管這些修改只能在緩沖區(qū)中進(jìn)行声诸,而不是實(shí)際地寫到磁盤。對(duì)讀出內(nèi)容所做的修改保存在內(nèi)存緩沖區(qū)中浴麻。 當(dāng)連接想要提交修改(或事務(wù))時(shí)囤攀,需要將保留鎖提升為排它鎖宫纬。
5、為了得到排它鎖蝌衔,還必須首先將保留鎖提升為未決鎖蝌蹂。獲得未決鎖之后,其它連接就不能再獲得新的共享鎖了剃允,但已經(jīng)擁有共享鎖的連接仍然可以繼續(xù)正常讀數(shù)據(jù)庫齐鲤。此時(shí),擁有未決鎖的連接等待其它擁有共享鎖的連接完成工作并釋放其共享鎖牡肉。
6淆九、一旦所有其它共享鎖都被釋放毛俏,擁有未決鎖的連接就可以將其鎖提升至排它鎖饲窿,此時(shí)就可以自由地對(duì)數(shù)據(jù)庫進(jìn)行修改了。所有以前對(duì)緩沖區(qū)所做的修改都會(huì)被寫到數(shù)據(jù)庫文件唧席。

二嘲驾、死鎖

為什么需要了解鎖的機(jī)制呢?為了避免死鎖。
考慮下面表所假設(shè)的情況徒仓。兩個(gè)連接——A 和 B——同時(shí)但完全獨(dú)立地工作于同一個(gè)數(shù)據(jù)庫誊垢。

A連接 B連接
sqlite> BEGIN;
sqlite> BEGIN;
sqlite> INSERTINTO foo VALUES('x');
sqlite> SELECT* FROM foo;
sqlite> COMMIT;
SQL error: database is locked
sqlite> INSERTINTO foo VALUES('x');
SQL error: database is locked

兩個(gè)連接都在死鎖中結(jié)束喂走。B 首先嘗試寫數(shù)據(jù)庫,也就擁有了一個(gè)未決鎖芋肠。A 再試圖寫帖池,但當(dāng)其 INSERT 語句試圖將共享鎖提升為保留鎖時(shí)失敗。
為了討論的方便睡汹,假設(shè)連接 A 和 B 都一直等待數(shù)據(jù)庫可寫囚巴。那么此時(shí),其它的連接甚至都 不能夠再讀數(shù)據(jù)庫了文兢,因?yàn)?B 擁有未決鎖(它能阻止其它連接獲得共享鎖)姆坚。那么時(shí)此,不僅 A 和 B 不能工作兼呵,其它所有進(jìn)程都不能再操作此數(shù)據(jù)庫了。
如果避免此情況呢?當(dāng)然不能讓 A 和 B 通過談判解決维苔,因?yàn)樗鼈兩踔敛恢辣舜说拇嬖凇?答案是采用正確的事務(wù)類型來完成工作。

三没宾、事物

事務(wù)的種類:

SQLite 有三種不同的事務(wù)沸柔,使用不同的鎖狀態(tài)。事務(wù)可以開始于:DEFERRED会钝、MMEDIATE 或 EXCLUSIVE工三。事務(wù)類型在 BEGIN 命令中指定:

BEGIN [ DEFERRED | IMMEDIATE| EXCLUSIVE ] TRANSACTION;

1俭正、一個(gè) DEFERRED 事務(wù)不獲取任何鎖(直到它需要鎖的時(shí)候),BEGIN 語句本身也不會(huì)做什么 事情——它開始于 UNLOCK 狀態(tài)掸读。默認(rèn)情況下 就是這樣的寺枉,如果僅僅用 BEGIN 開始一個(gè) 事務(wù)绷落,那么事務(wù)就是DEFERRED 的,同時(shí)它不會(huì)獲取任何鎖筐喳;
2函喉、當(dāng)對(duì)數(shù)據(jù)庫進(jìn)行第一次讀操作時(shí),它會(huì)獲取 SHARED 鎖梳毙;同樣捐下,當(dāng)進(jìn)行第一次寫操作時(shí)萌业,它會(huì)獲取 RESERVED鎖奸柬。 由 BEGIN 開始的IMMEDIATE 事務(wù)會(huì) 嘗試 獲取 RESERVED鎖 。如果成功抱婉, BEGIN IMMEDIATE保證沒有別的連接可以寫數(shù)據(jù)庫桌粉。但是番甩,別的連接可以對(duì)數(shù)據(jù)庫進(jìn)行讀操作; 但是,RESERVED鎖會(huì)阻止其它連接的 BEGIN IMMEDIATE或者 BEGIN EXCLUSIVE 命 令缘薛,當(dāng)其它連接執(zhí)行上述命令時(shí)宴胧, 會(huì)返回 SQLITE_BUSY 錯(cuò)誤。這時(shí)你就可以對(duì)數(shù)據(jù)庫進(jìn) 行修改操作了乞娄,但是你還不能提交显歧,當(dāng)你 COMMIT 時(shí),會(huì)返回SQLITE_BUSY 錯(cuò)誤范删,這意 味著還有其它的讀事務(wù)沒有完成拷肌,得等它們執(zhí)行完后才能提交事務(wù)。
3巨缘、EXCLUSIVE 事務(wù)會(huì)試著獲取對(duì)數(shù)據(jù)庫的 EXCLUSIVE 鎖若锁。這與 IMMEDIATE類似,但是一 旦成功靶病,EXCLUSIVE 事務(wù)保證沒有其它的連接,所以就可對(duì)數(shù)據(jù)庫進(jìn)行讀寫操作了娄周。 上節(jié)那個(gè)例子的問題在于兩個(gè)連接最終都想寫數(shù)據(jù)庫煤辨,但是它們都沒有放棄各自原來的鎖, 最終端三,SHARED 鎖導(dǎo)致了問題的出現(xiàn)鹃彻。
4悦穿、如果兩個(gè)連接都以 BEGIN IMMEDIATE開始事務(wù), 那么死鎖就不會(huì)發(fā)生止邮。在這種情況下欢摄,在同一時(shí)刻只能有一個(gè)連接進(jìn)入BEGIN IMMEDIATE笋粟, 其它的連接就得等待。BEGIN IMMEDIATE和 BEGIN EXCLUSIVE 通常被寫事務(wù)使用绿淋。就像同步機(jī)制一樣尝盼,它防止了死鎖的產(chǎn)生。 基本的準(zhǔn)則是:如果你正在使用的數(shù)據(jù)庫沒有其它的連接东涡,用 B EGIN 就足夠了疮跑。但是凸舵,如 果你使用的數(shù)據(jù)庫有其它的連接也會(huì)對(duì)數(shù)據(jù)庫進(jìn)行寫操作,就得使用 BEGINIMMEDIATE 或BEGIN EXCLUSIVE開始你的事務(wù)渐苏。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市仪吧,隨后出現(xiàn)的幾起案子鞠眉,更是在濱河造成了極大的恐慌械蹋,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件郊艘,死亡現(xiàn)場(chǎng)離奇詭異唯咬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)奈附,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門斥滤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勉盅,“玉大人草娜,你說我怎么就攤上這事≡兹颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長葡盗。 經(jīng)常有香客問我,道長胶背,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮砸抛,結(jié)果婚禮上直焙,老公的妹妹穿的比我還像新娘。我一直安慰自己奔誓,他們只是感情好厨喂,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著派阱,像睡著了一般斜纪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上腺劣,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天橘原,我揣著相機(jī)與錄音涡上,去河邊找鬼。 笑死芋酌,一個(gè)胖子當(dāng)著我的面吹牛耻警,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播甘穿,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼腮恩,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了温兼?” 一聲冷哼從身側(cè)響起秸滴,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎募判,沒想到半個(gè)月后荡含,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡届垫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年释液,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片装处。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖妄迁,靈堂內(nèi)的尸體忽然破棺而出寝蹈,到底是詐尸還是另有隱情,我是刑警寧澤登淘,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布箫老,位于F島的核電站,受9級(jí)特大地震影響黔州,放射性物質(zhì)發(fā)生泄漏耍鬓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一辩撑、第九天 我趴在偏房一處隱蔽的房頂上張望界斜。 院中可真熱鬧,春花似錦合冀、人聲如沸各薇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峭判。三九已至,卻和暖如春棕叫,著一層夾襖步出監(jiān)牢的瞬間林螃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國打工俺泣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疗认,地道東北人完残。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像横漏,于是被迫代替她去往敵國和親谨设。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容