2020互聯網公司面試 Mysql必問的技術點

mysql

[事務,隔離級別,存儲引擎,索引等]

事務

什麼是事務

事務是應用程序中一系列嚴密的操作,所有操作必須成功完成,否則在每個操作中所作的所有更改都會被撤消。也就是事務具有原子性,一個事務中的一系列的操作要麼全部成功,要麼一個都不做。

事務的結束有兩種,當事務中的所以步驟全部成功執行時,事務提交。如果其中一個步驟失敗,將發生回滾操作,撤消撤消之前到事務開始時的所以操作。

事務的ACID

事務具有四個特徵:原子性( Atomicity )、一致性( Consistency )、隔離性( Isolation )和持久性( Durability )。這四個特性簡稱爲 ACID 特性。

  1. 原子性。事務是數據庫的邏輯工作單位,事務中包含的各操作要麼都做,要麼都不做

  2. 一致性。事 務執行的結果必須是使數據庫從一個一致性狀態變到另一個一致性狀態。因此當數據庫只包含成功事務提交的結果時,就說數據庫處於一致性狀態。如果數據庫系統 運行中發生故障,有些事務尚未完成就被迫中斷,這些未完成事務對數據庫所做的修改有一部分已寫入物理數據庫,這時數據庫就處於一種不正確的狀態,或者說是 不一致的狀態。

  3. 隔離性。一個事務的執行不能其它事務干擾。即一個事務內部的操作及使用的數據對其它併發事務是隔離的,併發執行的各個事務之間不能互相干擾。

  4. 持久性。指一個事務一旦提交,它對數據庫中的數據的改變就應該是永久性的。接下來的其它操作或故障不應該對其執行結果有任何影響。

隔離級別

SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支持更高的併發處理,並擁有更低的系統開銷。

四種隔離級別

  1. Read Uncommitted(讀取未提交內容)

    在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用於實際應用,因爲它的性能也不比其他級別好多少。讀取未提交的數據,也被稱之爲髒讀(Dirty Read)。

  2. Read Committed(讀取提交內容)

    這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。這種隔離級別 也支持所謂的不可重複讀(Nonrepeatable Read),因爲同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。

  3. Repeatable Read(可重讀)

    這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在併發讀取數據時,會看到同樣的數據行。不過理論上,這會導致另一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一範圍的數據行時,另一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,會發現有新的“幻影” 行。InnoDB和Falcon存儲引擎通過多版本併發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。

  4. Serializable(可串行化)

    這是最高的隔離級別,它通過強制事務排序,使之不可能相互衝突,從而解決幻讀問題。簡言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。

髒讀,不可重複讀,幻讀

  • 髒讀(Drity Read)
    某個事務已更新一份數據,另一個事務在此時讀取了同一份數據,由於某些原因,前一個RollBack了操作,則後一個事務所讀取的數據就會是不正確的。

  • 不可重複讀(Non-repeatable read)
    在一個事務的兩次查詢之中數據不一致,這可能是兩次查詢過程中間插入了一個事務更新的原有的數據。

  • 幻讀(Phantom Read)
    在一個事務的兩次查詢中數據筆數不一致,例如有一個事務查詢了幾列(Row)數據,而另一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。

這四種隔離級別,分別有可能產生問題如下所示:

隔離級別 髒讀 不可重複讀 幻讀
Read Uncommitted
Read Committed(RC) ×
Repeatable Read(RR) × ×
Serializable × × ×

MVCC(多版本併發控制)

mysql的innodb採用的是行鎖,而且採用了多版本併發控制來提高讀操作的性能。

其實就是在每一行記錄的後面增加兩個隱藏列,記錄創建版本號和刪除版本號

而每一個事務在啓動的時候,都有一個唯一的遞增的版本號。

舉個栗子:

  • Insert
    比如插入一條記錄, 事務id是1 ,那麼記錄如下,記錄的創建版本號就是事務版本號。
    insert into table values (1, ‘test’);
id(主鍵) name(name) create version(創建版本號) delete version(刪除版本號)
1 test 1
  • Update
    採用的是先標記舊的那行記錄爲已刪除,並且刪除版本號是事務版本號,然後插入一行新的記錄的方式。
    針對上面那行記錄,事務Id爲2 要把name字段更新。
    update table set name= ‘new_value’ where id=1;
id(主鍵) name(name) create version(創建版本號) delete version(刪除版本號)
1 test 1 2
1 new_value 2
  • Delete
    就把事務版本號作爲刪除版本號。
    delete from table where id=1;
id(主鍵) name(name) create version(創建版本號) delete version(刪除版本號)
1 new_value 2 3
  • Select
    查詢時要符合以下兩個條件的記錄才能被事務查詢出來:

    1) 刪除版本號大於當前事務版本號,就是說刪除操作是在當前事務啓動之後做的。
    2) 創建版本號小於或者等於當前事務版本號,就是說記錄創建是在事務中(等於的情況)或者事務啓動之前。

保證了各個事務互不影響。從這裏也可以體會到一種提高系統性能的思路就是: 通過版本號來減少鎖的爭用。

另外,只有read-committed和 repeatable-read 兩種事務隔離級別才能使用MVCC

read-uncommited由於是讀到未提交的,所以不存在版本的問題

而serializable 則會對所有讀取的行加鎖。

存儲引擎

此處只列舉兩種,MyISAM 與 InnoDb

InnoDb

  1. 支持ACID的事務,支持事務的四種隔離級別;
  2. 支持行級鎖及外鍵約束:因此可以支持寫併發;
  3. 不存儲總行數;
  4. 一個InnoDb引擎存儲在一個文件空間(共享表空間,表大小不受操作系統控制,一個表可能分佈在多個文件裏),也有可能爲多個(設置爲獨立表空,表大小受操作系統文件大小限制,一般爲2G),受操作系統文件大小的限制;
  5. 主鍵索引採用聚集索引(索引的數據域存儲數據文件本身),輔索引的數據域存儲主鍵的值;因此從輔索引查找數據,需要先通過輔索引找到主鍵值,再訪問輔索引;最好使用自增主鍵,防止插入數據時,爲維持B+樹結構,文件的大調整。

MyISAM

  1. 不支持事務,但是每次查詢都是原子的;
  2. 支持表級鎖,即每次操作是對整個表加鎖;
  3. 存儲表的總行數;
  4. 一個MYISAM表有三個文件:索引文件、表結構文件、數據文件;
  5. 採用菲聚集索引,索引文件的數據域存儲指向數據文件的指針。輔索引與主索引基本一致,但是輔索引不用保證唯一性。

InnoDb與MyISAM索引的區別

兩種存儲引擎都是採用B+Tree的結構

MYISAM的主索引結構如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zFDnyqwB-1578388117322)(http://blog.guowenbo.top/images/2018-12-03/mysql_1.png)]

輔索引如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-MPdq5MAl-1578388117323)(http://blog.guowenbo.top/images/2018-12-03/mysql_2.png)]

InnoDb的主索引如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LuGOaMsI-1578388117323)(http://blog.guowenbo.top/images/2018-12-03/mysql_3.png)]

輔索引如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-bRJUnDE2-1578388117324)(http://blog.guowenbo.top/images/2018-12-03/mysql_4.png)]

兩種索引數據查找過程如下:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-74lvtNHC-1578388117324)(http://blog.guowenbo.top/images/2018-12-03/mysql_5.png)]

索引相關

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