1. 程式人生 > >Innodb中的事務和鎖以及MVCC

Innodb中的事務和鎖以及MVCC

螞蟻金服面試,主要問了一些jvm和mysql的知識,有些問題回答的模稜兩可,再次總結一下。mysql因為其外掛式儲存引擎以及其較小的體積成為了許多應用中資料庫的首選,Innodb引擎支援事務,外來鍵並且支援行鎖,被廣泛的應用於OLTP業務中。

1.mysql的體系架構
mysql體系
上圖是mysql的總體架構,可以看到外掛式的儲存引擎只是mysql的一個元件而已,引擎是基於表的,而並非是基於資料庫的。
有一個問題:qcache和Innodb buffer pool有什麼區別?
這個問題的本質還是儲存引擎是基於表的,而不是基於資料庫的這句話,innodb buffer pool是基於表的,儲存的是表的資料,當查詢資料時,會首先從記憶體中進行查詢,如果記憶體中存在,資料將直接從記憶體中返回,從而提高查詢的響應時間;而qcache是基於資料庫的,快取的是sql語句及其對應的結果集,qcache會跟蹤系統中的每張表,若表發生變化,則和張表相關的所有查詢快取全部失效,且任何包含不確定結果的查詢(如now())均不會被快取。當檢查到qcache有效的時候,mysql不會對sql語句做解析,優化等任何的處理,直接將結果集返回。

2.Innodb和MyISAM的區別
這兩個引擎可謂是mysql中最常見的兩個引擎,前者適用於OLTP業務中,而後者適用於OLAP業務中。下面給出一張表來對比兩者區別
innodb vs myisam
關於聚集索引有一問題:
Innodb中聚集索引和非聚集索引的區別?
Innodb儲存引擎表示索引組織表。即表中資料行順序按照主鍵順序存放(邏輯上均連續,物理上可能不一定連續,視具體情況,因為維護成本太高),而聚集索引就是每張表主鍵構成的一棵B+樹。同時葉子節點存放的即為整張表的行記錄資料的指標。由於實際的資料頁只能按照一棵B+樹進行排序所以一張表也只能擁有一個聚集索引,用主鍵進行範圍查詢是極快的,因為由雙向連結串列進行邏輯上的連結。下圖便是一個實際的聚集索引示例:
cluster index


非聚集索引的資料結構仍然是B+樹,葉子節點不包含資料行的資料。葉子節點除了包含鍵值外,還包含相應資料行的聚集索引鍵,同樣的查詢 勢必要多進行一倍的IO操作,下圖是一個非聚集索引的示意圖:
secondary index
另外提一下,MyISAM中採用堆表的表型別,行資料的儲存按照插入的順序存放。自然也談不上什麼聚集索引,以行識別符號來標識資料行。
除此之外還有一個問題:
為什麼要採用B+樹做索引,而不採用B樹做索引:
我認為有2點原因:
1).B樹雖然非葉子節點中也含有資料,有可能在查詢的時候只需走比B+樹要少的層即可查詢到資料。但是對於大多數節點(位於葉子的),B樹由於每個節點都存放了聚集索引鍵/資料行的指標,導致B樹節點大小較B+樹要大,所以佔用更多空間,導致更多的磁碟IO
2).更重要的一點,在B樹中,如果想遍歷一個範圍或者說遍歷所有資料,需要進行中序遍歷,但是在B+樹中,可以通過雙向連結串列來遍歷所有葉子節點。

3.事務的ACID特性以及mysql中如何保證這4個特性
這是一個特別好的問題,也是這篇blog的中點,直接把事務的特性和mysql的鎖和MVCC一起很深入的考察了一下,PS:我發現螞蟻金服的人面試,一不提前約時間,二不問具體問題,就問一個方面,讓你談談對這方面的理解,然後你說到哪他感興趣了就深入的問問。
3.1 事務ACID特性的理解
A(Atomic):原子性是指資料庫的事務是一個不可分割的工作單位,只有資料庫事務都成功才算成功,任何一個SQL的失敗,資料庫狀態都必須回退到事務開始前的狀態
C(Consistence):一致性是指事務將資料庫的狀態從一種狀態轉變為下一個一致的狀態。在事務的開始和結束後,資料庫的完整性約束都沒有被破壞。
I(Isolation):隔離性是指事務之間對資料物件的讀寫是相互隔離的,具體是提交後可見還是提交後也不可見取決於隔離等級,前面兩種情況分別為提交讀(RC)和可重複讀(RR)。
D(永續性):永續性是指事務一旦提交,其修改是永久性的,即使還未寫入磁碟時發生宕機,也能恢復資料。
3.2 多版本併發控制(MVCC)
在innodb中“MVCC多版本一致性讀”功能的實現是基於undo-log的。主要是為Repeatable-Read事務隔離級別做的。
innodb儲存的最基本row中包含一些額外的儲存資訊,如下圖所示:
ROW_REC
DATA_TRX_ID:最新修改此行記錄的事務ID
DATA_ROLL_PTR:指向本資料行undo log,之前版本的資料就存於這裡
DELETE BIT:標識此記錄是否被刪除
DB_ROW_ID:若指定了主鍵,則主鍵生成聚集索引,若未指定,以該列自動生成聚集索引。
當執行一個update語句時過程如下:
用排它鎖鎖定改行–>修改該行–>寫redo log–>寫undo log–>更新DATA_TRX_ID以及更新DATA_ROLL_PTR指向undo log中修改前的行。
當使用MVCC SELECT資料時(主要用於RR隔離):
1.如果行未被刪除,DELETE BIT=0,則只查詢事務ID版本小於該事務ID的記錄
2.如果行被刪除,DELETE BIT=0,則版本號必須是未定義的或者大於當前事務的版本號,確定了當前事務開始之前,行沒有被刪除。
MVCC詳解
MVCC讀的執行過程
在RC和RR隔離級別下,Innodb都會採用非鎖定的一致性讀,在RC下,對於快照資料,非一致性讀總是讀取非鎖定行的最新一份快照資料,而在RR下,會去讀取事務開始時的快照資料。
3.3 鎖
Innodb中基本鎖有以下4種:
行級鎖
1). 共享鎖(S Lock) : 允許事務讀一行資料
2). 排它鎖(X Lock) : 允許事務刪除或更新一行資料
表級鎖
3). 意向共享鎖(IS Lock):事務想要獲得一張表中某幾行的共享鎖
4). 意向排它鎖(IX Lock):事務想要獲得一張表中某幾行的排它鎖
由於Innodb引擎支援的均為行鎖,所以意向鎖其實不會阻塞除全表掃描之外的任何請求
Innodb中行鎖有三種基本的演算法:
1). record lock : 單個行記錄上的鎖
2). gap lock:鎖定一個範圍,但不包含記錄本身
3). next-key lock : record lock + gap lock鎖定一個範圍,並且鎖定記錄本身。避免幻讀
鎖問題:
1). 髒讀:所謂髒資料就是指那些尚未提交的非一致的資料,和髒頁完全不同,髒頁由於記憶體和磁碟不同步造成,最終終會達到一致。僅有RU下會出現髒讀。
2). 不可重複讀/幻讀:innodb採用next-keys鎖機制,不僅鎖住行記錄還會鎖住範圍,避免不可重複讀和幻讀
3). 丟失更新:資料庫層面上可以避免,但應用程式中可能由於網路延遲等原因,一定要注意。
其實在innodb中,RC和RR都採用的是非鎖定的一致性讀,也不會因為鎖而阻塞。
3.4 Innodb中如何實現ACID
隔離性:鎖和MVCC
其他:redo undo
(待補充)