(三)鎖和事務

摘要:

今天主要給大家介紹一下數據庫的鎖和事務。數據庫的事務主要解決的問題是併發控制,試想一下,如何多個用戶併發的去修改同一記錄,會發生什麼?


1、鎖

鎖的類型:

  • 共享鎖:也叫讀鎖,多個客戶可以同時讀取同一個資源,互不干擾。
  • 排它鎖:也叫寫鎖,寫鎖的優先級高於讀鎖,當寫鎖被佔用的時候,這個時候讀也是會被等待的,其他客戶寫也會等待。

鎖的粒度:

  • 表鎖:粒度比較粗,鎖定整張表。
    特點:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發出鎖衝突的概率最高,併發度最低。
  • 行鎖:行級鎖可以最大程度的支撐併發處理,同時也帶來了最大的鎖開銷。
    特點:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖衝突的概率最低,併發度也最高。
  • 頁鎖:介於兩者之間。

鎖的實現:

  • 悲觀鎖:悲觀鎖指對數據被意外修改持保守態度,依賴數據庫原生支持的鎖機制來保證當前事務處理的安全性,防止其他併發事務對目標數據的破壞或破壞其他併發事務數據,將在事務開始執行前或執行中申請鎖定,執行完後再釋放鎖定。這對於長事務來講,可能會嚴重影響系統的併發處理能力。 自帶的數據庫事務就是典型的悲觀鎖。
  • 樂觀鎖:樂觀鎖(Optimistic Lock),顧名思義,就是很樂觀,每次去拿數據的時候都認爲別人不會修改,所以不會上鎖,但是在提交更新的時候會判斷一下在此期間別人有沒有去更新這個數據。樂觀鎖適用於讀多寫少的應用場景,這樣可以提高吞吐量。一般是加一個版本號字段 每次更新時候比較版本號。

2、事務

1.什麼是事務?

事務是指一個單元的一系列SQL集合,要麼都執行,要麼都不執行。如果不對數據庫進行併發控制,可能會產生 髒讀、非重複讀、幻像讀、丟失修改的異常情況。

事務的特性(ACID):

  • 原子性(automicity):事務中的所有SQL,要麼全執行,要麼全部不執行。這就是事務的原子性。
  • 一致性(consistency):轉賬前,A和B的賬戶中共有500+500=1000元錢。轉賬後,A和B的賬戶中共有400+600=1000元。
  • 隔離性(isolation):在A向B轉賬的整個過程中,只要事務還沒有提交(commit),查詢A賬戶和B賬戶的時候,兩個賬戶裏面的錢的數量都不會有變化。
  • 持久性(durability):一旦轉賬成功(事務提交),兩個賬戶的裏面的錢就會真的發生變化。

2.什麼是髒讀?幻讀?不可重複讀?什麼是事務的隔離級別?Mysql的默認隔離級別是?

  • 髒讀:事務A讀取了事務B更新的數據,然後B回滾操作,那麼A讀取到的數據是髒數據。
  • 不可重複讀:事務 A 多次讀取同一數據,事務 B 在事務A多次讀取的過程中,對數據作了更新並提交,導致事務A多次讀取同一數據時,結果 不一致。
  • 幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改爲ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。也就是可以插入新的行記錄。

事務的隔離級別:

  • Read uncommitted(讀未提交):就是一個事務可以讀取另一個未提交事務的數據。會造成髒讀,不可重複讀。
  • Read committed(讀已提交):就是一個事務要等另一個事務提交後才能讀取數據。但還是不可重複讀。
  • Repeatable read(可重複讀):就是在開始讀取數據(事務開啓)時,不再允許修改操作。
  • Serializable (串行化):Serializable 是最高的事務隔離級別,在該級別下,事務串行化順序執行,可以避免髒讀、不可重複讀與幻讀。但是這種事務隔離級別效率低下,比較耗數據庫性能,一般不使用。

Mysql的默認隔離級別是:Repeatable read!!

3.什麼是死鎖?怎麼解決?

死鎖:兩個或多個事務相互佔用了對方的鎖,就會一直處於等待鎖的狀態。

常見的解決死鎖的方法:

1、如果不同程序會併發存取多個表,儘量約定以相同的順序訪問表,可以大大降低死鎖機會。
2、在同一個事務中,儘可能做到一次鎖定所需要的所有資源,減少死鎖產生概率;
3、對於非常容易產生死鎖的業務部分,可以嘗試使用升級鎖定顆粒度,通過表級鎖定來減少死鎖產生的概率;
如果業務處理不好可以用分佈式事務鎖或者使用樂觀鎖

4.多版本併發控制

MySQL的大多數事務型存儲引擎實現的都不是簡單的行級鎖。基於併發性能的考慮,他們一般都同時實現了多版本併發控制(MVCC),不僅MySQL,包括Oracale、PostgreSQL等其他數據庫都各自實現了MVCC,但基於實現的機制不盡相同,因爲MVCC沒有一個統一的標準。
InnoDB的MVCC,是通過在每行記錄後面保存兩個隱藏的列來實現的,一個是創建時間,一個是系統版本號。每開始一個新的事物,系統版本號會自動遞增。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章