MySql中的事務,隔離機制以及涉及到的鎖總結

MySql中的事務,隔離機制以及涉及到的鎖總結

純手打,希望可以幫助大家, 轉載的話附上鍊接就可以啦. 希望大家多提意見,逐步完善


  1. MySql事務

事務就是一組SQL要麼全部成功執行,要麼全都不執行,哪怕其中任何一個SQL出現操作異常執行過的SQL也會進行回滾

事務的性質(A C I D)

  • Atomic **原子性:**整個事務是一個原子操作,要麼全部成功,要麼會回滾到初始狀態,just like 整個事務中的sql從未執行過一樣
  • Consistency **一致性:**數據庫經過事務以後,整個數據庫狀態是完美從一個狀態到另一個狀態,是完全符合規則的.例如 A向B轉了一百塊,最後的狀態是A的賬戶少了100,B的賬號多了100. 這就是一致性
  • Isolation **隔離性:**數據庫允許並行多個事務執行數據的更新,隔離性可以防止多個事務併發交叉執行而導致的數據不一致問題. 事務隔離分爲多個級別,包括 未提交(Read uncommitted),讀提交(read committed),可重複讀(repeatable read)和串行化(Serializable)
  • Durability **持久性:**一個事務執行完畢,對數據的修改時永久的,及時系統故障也不會丟失
  1. 事務的隔離級別

    離級別 髒讀可能性 不可重複讀可能性 幻讀可能性 加鎖讀
    ead Uncommitted Yes Yes Yes N0
    ead Committed No Yes Yes No
    epeatable Read No No Yes No
    erializable No No No Yes

    隔離級別是針對在多個事務在併發情況下出現的數據問題例如:髒讀,不可重複讀,幻讀採取的不同隔離標準.我們按照數據安全級別由低到高來講下上邊的四個隔離級別:

    • 未提交讀(Read uncommitted):最低的隔離級別,啥也保證不了,一般不會使用
    • 已提交讀(Read committed):解決了髒讀的問題,不會讀取到其他事物事物未提交所做的新增和更新
    • 可重複讀(Repeatable read):解決了髒讀,和不可重複讀,但是會出現幻讀. Mysql的InnoDB引擎默認就是該隔離級別
    • 串行化(Serializable):最高級別,但是併發處理能力最低,魚和熊掌不能兼得

    這是四個隔離級別,那麼我們講一下上邊出現的數據問題,究竟什麼是髒讀?不可重複讀?幻讀?

    • 髒讀:事務A會讀取到事務B還沒有提交事務之前做的數據更改,事務A此時讀到的數據還沒有真正持久化到數據庫,萬一事務B回滾了,那麼事務A讀到的數據就是’髒’的
    • 不可重複讀: 不可重複讀面向的重點是update/delete情況下出現的,在一個事務A中假設查詢了兩次賬戶餘額,由於別的事務更新操作,兩次查詢到的賬戶餘額是不一樣的,此時就說是不可重複讀
    • 幻讀: 幻讀主要針對別的數據進行的Insert操作,比如在一個事務A中要插入一條ID爲10的數據,並且查詢的時候沒有ID爲10的數據存在,但是插入的時候報錯,說ID重複,這就是典型的幻讀場景

    針對以上可能會因爲併發事務導致的問題主要解決方式有如下兩種

    1. 在讀取數據之前,對其加鎖,阻止其他事務對其進行修改,那麼以上問題都可解決
    2. 另一種是不用加任何鎖,通過一定機制生成一個數據請求時間點的一致性數據快照(Snapshot),並用這個快照來提供一定級別(語句級或事務級)的一致性讀取。從用戶的角度來看,好像是數據庫可以提供同一數據的多個版本,因此,這種技術叫做數據多版本併發控制(MultiVersion Concurrency Control,簡稱MVCC或MCC),也經常稱爲多版本數據庫。
  2. MySQL中的鎖

    MyISAM引擎的鎖只支持表鎖,還有支持併發條件下的尾部插入,MyISAM也不支持事務,在此不做爲重點講解.

    InnoDB引擎支持事務,並且不僅支持表鎖,還支持行鎖來提高併發下的吞吐量

    • 表鎖:在操作更新或者讀取的時候,將整個表鎖住,不允許任何對該表的查找和修改,保證了表數據的正確性,但是導致併發效率很低,很多會話會處於等待狀態浪費資源,造成很低的吞吐量

    • 行鎖:InnoDB實現了兩種行鎖

      1. 共享鎖(S):允許多個事務獲取該共享鎖Share Lock,但是大家都不能對該行數據進行修改,要想修改該行數據(要獲取該行的排它鎖,也就是寫鎖 必須等待所以共享鎖事務釋放完畢纔可以)

      2. 排它鎖(X):一個事務一旦獲取數據A的排它鎖,其他任何事物都無法獲取鎖(但是可以進行查詢,只是不能獲取共享鎖,排它鎖而已),只能進行等待,排它鎖即可讀數據又可以寫數據

      3. 意向鎖:意向鎖是表級鎖,其設計目的是爲了揭示事務中下一行將要被請求鎖的類型,InnoDB中的兩個表鎖

        意向共享鎖(IS):表示事務準備給數據加共享鎖,也就是加共享鎖之前首先要獲得該表的IS鎖

        意向排它鎖(IX):表示事務準備給數據行加排它鎖,說明一個事務在對一行數據加排它鎖之前首先必須獲得該數據的IX鎖

        意向鎖是InnoDB自動加的,不需要用戶干預

    鎖的總結:

    對於insert、update、delete,InnoDB會自動給涉及的數據加排他鎖(X);對於一般的Select語句,InnoDB不會加任何鎖,事務可以通過以下語句給顯示加共享鎖或排他鎖。

    共享鎖:SELECT ... LOCK IN SHARE MODE;

    排他鎖:SELECT ... FOR UPDATE;

  3. 間隙鎖(Next-Key鎖)

    間隙鎖舉例: 當前user表中有ID爲:1-101條數據

    當執行select * from user where ID>100 for update 這個範圍查找並且獲取排它鎖

    加鎖情況: 不僅僅對滿足條件且真實存在的ID=101數據加鎖, 對不存在數據庫中的飯爲 ID>101 這個很大的間隙加鎖, 也就是其他嘗試插入的SQL會阻塞等待

  4. 深入瞭解行鎖:

    1. 在InnoDB當中,行鎖是鎖在對應的索引上,此處應該注意只有通過索引查找的數據纔會使用行鎖,否則將使用表鎖,需要注意這點,非常影響效率
    2. 雖然不是相同的行,如果使用的是相同的索引,則獲取鎖的兩行的時候會衝突,因爲索引相同,則鎖兩個行鎖資源一樣.
    3. 即便在條件中使用了索引字段,但是否使用索引來檢索數據是由MySQL通過判斷不同執行計劃的代價來決定的,如果MySQL認爲全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下InnoDB將使用表鎖,而不是行鎖。因此,在分析鎖衝突時,別忘了檢查SQL的執行計劃,以確認是否真正使用了索引。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章