Android數據庫鎖機制

今天介紹下Android數據庫鎖機制、性能優化的點,之前去面試的時候面試官問我能同時在同個數據庫里寫兩個記錄么,對兩個不同的表寫數據可以么?我知道肯定是不行的,但說不出個所以然,只能淺顯地說數據庫整體是一個文件,保證并發性的話不能同時對一個文件做寫操作哈。那接下來主要會對SQL鎖機制做個介紹。


  • 性能優化
  • 鎖機制

1.性能優化

1.1數據庫insert、query、update、delete的API與execSQL、rawQuery函數執行插入、查詢、更新、刪除語句操作花費時間的對比。
(1)批量執行1000條,則SqliteDatabase提供的insert、query、update、delete函數和直接execSQL、rawQuery函數的效率差不多。
(2)批量執行10w條,SqliteDatabase提供的insert、query、update、delete函數相對效率比較低。execSQL省去了拼接sql語句的步驟,當數據庫越大,差別就越大。
1.2批量操作效率
在數據庫中插入大量數據,如果使用遍歷insert操作會導致應用響應緩慢,每一次insert操作都會開啟一個事務,這樣都會執行一次磁盤操作。我們可以通過顯示添加事務來提高效率

 db.beginTransaction();
 try {
  for(int i = 0; i < 10000; i++) {
    insert(db, c);
  }
  db.setTransactionSuccessful();
 } catch(Exception ex) {
 } finally {
   db.endTransaction();
 }

這樣會將全部要執行的sql語句先緩存在內存當中,然后等到Commit的時候一次性寫入數據庫,保證數據庫文件只被打開關閉了一次。

2.鎖機制

SQLite是基于鎖來實現并發控制的,SQLite的鎖是粗粒度的,所以是輕量級的,當一個連接要寫數據庫時,所有其他的連接都被鎖住,直到寫連接結束它的事務。
2.1鎖的狀態
SQLite數據庫連接有5種狀態

image.png

未加鎖:
未和數據庫建立連接、已建立連接但還沒訪問數據庫、已用BEGIN開始了一個事務但未開始讀寫數據庫,處于這些情形時是未加鎖狀態。
共享鎖:
連接需要從數據庫中讀取數據時,需要申請獲得一個共享鎖,如果獲取成功,則進入共享狀態。
預留鎖:
連接需要寫數據至數據庫時,首先申請一個預留鎖,一個數據庫同時只能有一個預留鎖,預留鎖可以與共享鎖共存。獲得預留鎖后會進入預留狀態,這時會先在緩存區中進行寫操作,操作后的結果依然保存在緩存區中,未真正寫入數據庫。
未決鎖:
連接從預留升級為排它前,需要先升級為未決鎖,這時其他的連接就不能獲取到共享鎖了,但已經擁有共享鎖的連接仍然正常讀數據庫,此時,擁有未決鎖的連接等待其他擁有共享鎖連接完成工作并釋放其共享鎖后,才能提升到排它鎖。
排它鎖:
連接需要提交修改時,需要將預留鎖升級為排它鎖,這時候其他鏈接都無法獲取任何鎖,直到當前連接的排它狀態結束。
一個連接讀數據庫的流程如下:
image.png

一個連接寫數據庫的流程如下:

image.png

但在實際中可能會出現死鎖的問題,例如在使用事務的情況下。

image.png

執行順序1:連接A獲取一個未加鎖
執行順序2:連接B獲取一個未加鎖
執行順序3:連接B要執行寫操作,獲得預留鎖(數據庫連接只能一次有一個預留鎖)
執行順序4:連接A要執行讀操作,獲取共享鎖
執行順序5:連接B要升級為排它鎖前,在執行提交數據庫的操作前,先升級成未決鎖(這時候不能有新的共享鎖了)
執行順序6:連接B要升級為排它鎖,但可能存在4的操作耗時久,共享鎖未被釋放,連接B需等待
執行順序7:連接A要執行寫操作,需要獲取預留鎖
執行順序8:連接A獲取預留鎖失敗,必須先等連接B釋放未決鎖
于是連接A和連接B相互等待對方,發生死鎖。

那么,如何避免這種死鎖情況呢?就要談談事務類型了。
2.2事務類型
DEFERRED
不獲取任何鎖,這種是正常執行流程從上往下的,但對數據庫進行連接時它本身是不會獲取任何鎖的,當對數據庫進行讀操作時,會獲取共享鎖,當對寫操作時,會獲取預留鎖。
IMMEDIATE
在BEGIN時事務會嘗試獲取預留鎖。如果獲取成功,能保證沒有其他可以對數據庫可以進行寫操作,但可以進行讀操作。通俗而言就是當前事務在沒有結束之前,任何其他線程或進程都無法對數據庫進行寫操作。
EXCLUSIVE
事務會嘗試獲取排它鎖。一旦獲取成功,保證沒有額外的連接,這樣就能保證對數據庫進行讀寫操作。通俗而言就是當前事務在沒有結束之前,任何其他線程或進程都無法對數據庫進行讀寫操作。
其實上面死鎖的情況主要是由于一個共享鎖未釋放導致兩個連接互相等待對方。那么如果兩個連接都是以IMMEDIATE的方式開啟事務的話,那么當下只能有一個連接獲取預留鎖,其他的連接就得等它操作完。
可能說的有點懸乎,那么我們看下安卓開啟事務的代碼。

image.png

beginTransaction():使用EXCLUSIVE這種方式的。
beginTransactionNonExclusive():使用IMMEDIATE這種方式的。
具體內部邏輯如下:
image.png

所以說默認情況下使用事務時,只允許一個連接進行數據庫讀寫,這樣保證了并發性。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容