MySql 事物及隔離級別

1、事務的基本要素(ACID)

  一、原子性(Atomicity):事務開始後全部操做,要麼所有作完,要麼所有不作,不可能停滯在中間環節。事務執行過程當中出錯,會回滾到事務開始前的狀態,全部的操做就像沒有發生同樣。也就是說事務是一個不可分割的總體,就像化學中學過的原子,是物質構成的基本單位。mysql

   二、一致性(Consistency):事務開始前和結束後,數據庫的完整性約束沒有被破壞 。好比A向B轉帳,不可能A扣了錢,B卻沒收到。算法

   三、隔離性(Isolation):同一時間,只容許一個事務請求同一數據,不一樣的事務之間彼此沒有任何干擾。好比A正在從一張銀行卡中取錢,在A取錢的過程結束前,B不能向這張卡轉帳。sql

   四、持久性(Durability):事務完成後,事務對數據庫的全部更新將被保存到數據庫,不能回滾。數據庫

2、事務的四種隔離級別

在數據庫操做中,爲了有效保證併發讀取數據的正確性,提出的事務隔離級別。咱們的數據庫鎖,也是爲了構建這些隔離級別存在的。
隔離級別 髒讀(Dirty Read) 不可重複讀(NonRepeatable Read) 幻讀(Phantom Read)
未提交讀(Read uncommitted) 可能 可能 可能
已提交讀(Read committed) 不可能 可能 可能
可重複讀(Repeatable read) 不可能 不可能 可能
可串行化(Serializable ) 不可能 不可能 不可能
  • 未提交讀(Read Uncommitted):容許髒讀,也就是可能讀取到其餘會話中未提交事務修改的數據
  • 提交讀(Read Committed):只能讀取到已經提交的數據。Oracle等多數數據庫默認都是該級別 (不重複讀)
  • 可重複讀(RepeatedRead):可重複讀。在同一個事務內的查詢都是事務開始時刻一致的,InnoDB默認級別。在SQL標準中,該隔離級別消除了不可重複讀,可是還存在幻象讀。mysql默認級別:可重複讀
  • 串行讀(Serializable):徹底串行化的讀,每次讀都須要得到表級共享鎖,讀寫相互都會阻塞

3、事務的併發問題

  一、髒讀:事務A讀取了事務B更新的數據,而後B回滾操做,那麼A讀取到的數據是髒數據網絡

  二、不可重複讀:事務 A 屢次讀取同一數據,事務 B 在事務A屢次讀取的過程當中,對數據做了更新並提交,致使事務A屢次讀取同一數據時,結果 不一致。併發

  三、幻讀:系統管理員A將數據庫中全部學生的成績從具體分數改成ABCDE等級,可是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺同樣,這就叫幻讀。性能

  小結:不可重複讀的和幻讀很容易混淆,不可重複讀側重於修改,幻讀側重於新增或刪除。解決不可重複讀的問題只需鎖住知足條件的行,解決幻讀須要鎖表。優化

4、MVCC在MySQL的InnoDB中的實現

在InnoDB中,會在每行數據後添加兩個額外的隱藏的值來實現MVCC,這兩個值一個記錄這行數據什麼時候被建立,另一個記錄這行數據什麼時候過時(或者被刪除)。 在實際操做中,存儲的並非時間,而是事務的版本號,每開啓一個新事務,事務的版本號就會遞增。 在可重讀Repeatable reads事務隔離級別下:code

  • SELECT時,讀取建立版本號<=當前事務版本號,刪除版本號爲空或>當前事務版本號。
  • INSERT時,保存當前事務版本號爲行的建立版本號。
  • DELETE時,保存當前事務版本號爲行的刪除版本號。
  • UPDATE時,插入一條新紀錄,保存當前事務版本號爲行建立版本號,同時保存當前事務版本號到原來刪除的行。

經過MVCC,雖然每行記錄都須要額外的存儲空間,更多的行檢查工做以及一些額外的維護工做,但能夠減小鎖的使用,大多數讀操做都不用加鎖,讀數據操做很簡單,性能很好,而且也能保證只會讀取到符合標準的行,也只鎖住必要行。排序

咱們無論從數據庫方面的教課書中學到,仍是從網絡上看到,大都是上文中事務的四種隔離級別這一模塊列出的意思。

  • MVCC 總結:爲了實現快照讀(讀寫不衝突)

五 MySQL死鎖

死鎖是隻兩個或者多個事務在同一個資源上相互佔用,並請求鎖定對方佔用的資源。從而致使循環的現象。當多個事務試圖以不一樣的順序鎖定資源時,就可能產生死鎖。多個事務同事鎖定同一個資源時,也會產生死鎖。例如,兩個事務同事處理stockprice表。

事務1:
    start transaction;
    update stockprice set close = 45.50 where stock_id = 4 and date = '2019-05-05';
    update stockprice set close = 36.66 where stock_id = 3 and date = '2019-05-06';
    commit
事務2:
    start transaction;
    update stockprice set high = 33.33 where stock_id = 3 and date = '2019-05-06';
    update stockprice set high = 35.66 where stock_id = 4 and date = '2019-05-05';
    commit

若是連個都執行了第一條update 語句,跟新了一行數據,同事也鎖定了該行數據,接着每一個事務都嘗試去執行第二條update語句,發現該行已經被對方鎖定,而後兩個事務都等待對方釋放鎖,同事又持有對方須要的鎖,則陷入死循環。除非有外部因素介入才能解除死鎖。

六 EXPLAIN 分析語句

1. select_type:查詢類型,
    1. simple:通常是簡單查詢,不使用union或子查詢
    2. subquery:子查詢中的第一個select
    3. primary:最外層的select
2. type:mysql找到所需行的方式,又叫「訪問類型」,由差到好的順序:
    1. type=ALL:全表掃描(通常須要進行優化)
    2. type=index:整個索引掃描(不知足最左匹配可能會引發)
    3. type=range:使用一個索引來檢索給定範圍的行
    4. type=ref:mysql會根據特定的算法快速查找到某個符合條件的索引,而不是會對索引中每個數據都進行一一的掃描判斷
    5. type=eq_ref:相似ref,區別是使用的索引是惟一索引
    6. const、system:常量匹配,主鍵匹配
3. rows:找到所需記錄須要讀取的行數(估計值)
4. extra:詳細信息,常見:
    1. Using index:只查詢索引就能獲得結果(覆蓋索引)
    2. Using where:須要經過索引再檢索實際數據進行過濾
    3. Using temporary:使用臨時表
    4. Using filesort:使用臨時文件排序

七 鎖的定義

1.每次老是被什麼共享鎖、排他鎖給繞暈了。簡單實際一點。就只有 讀鎖 寫鎖 兩種鎖。對應關係以下:

鎖類型 描述
共享鎖(讀鎖 其餘事務能夠讀,但不能寫。
排他鎖(寫鎖) 其餘事務不能讀取,也不能寫。

2.樂視鎖和悲觀鎖

  • 樂觀鎖:是一種解決問題的邏輯。採用版本號的處理方式實現
  • 悲觀鎖:是借用mysql InnoDB 行鎖來實現的(where 條件必需要加索引)。

    select * from user whereid = 10 for update

3.行鎖和表鎖

  • 行鎖:顧名思義就是鎖定每一行
  • 表鎖:顧名思義就是鎖定整張表

4.其餘mysql 內部實現的鎖機制

隱式鎖、間隙鎖等。
相關文章
相關標籤/搜索