事務不同的隔離級別實現原理
一、概述
MySQL數據庫有多種存儲引擎:比如:MyISAM、InnoDB、MERGE、MEMORY(HEAP)、BDB(BerkeleyDB)、EXAMPLE、FEDERATED、ARCHIVE、CSV、BLACKHOLE等等,最常見的也就是MyISAM和InnoDB了。
其中MylSAM是MySQL的默認搜索引擎,但是不支持事務,InnoDB支持事務。
一、AQS原理
AQS:AbstractQuenedSynchronizer抽象的隊列式同步器。是除了java自帶的synchronized關鍵字之外的鎖機制。
AQS的全稱為(AbstractQueuedSynchronizer),這個類在java.util.concurrent.locks包
AQS的核心思想是,如果被請求的共享資源空閑,則將當前請求資源的線程設置為有效的工作線程,並將共享資源設置為鎖定狀態,如果被請求的共享資源被占用,那么就需要一套線程阻塞等待以及被喚醒時鎖分配的機制,這個機制AQS是用CLH隊列鎖實現的,即將暫時獲取不到鎖的線程加入到隊列中
二、排它鎖(Exclusive Lock)
簡稱x鎖,又稱寫鎖、獨占鎖。
若事務T對數據對象A加上X鎖,則只允許T讀取和修改A,其他任何事物不能再對A加任何類型的鎖,直到T釋放A上的鎖。這就保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。
三、共享鎖(Share lock)
共享鎖(Share lock),簡稱S鎖,又稱讀鎖,這個鎖和之前的排它鎖x鎖有區別,主要是讀取操作創建的鎖。其他用戶可以並發讀取數據,但任何事務都不能對數據進行修改(獲取數據上的排它鎖),直到已釋放所有共享鎖。
四、InnoDB的四種事務的隔離級別,分別是怎么實現的?
使用鎖機制和MVCC版本控制實現的
MVCC:
4.1、讀未提交
這種事務隔離級別下,select語句不加鎖
4.2、串行化
這種事務的隔離級別下,所有select語句都會被隱式的轉化為select ... in share mode。
這可能導致,如果有未提交的事務正在修改某些行,所有讀取這些行的select都會被阻塞住。
4.3、可重復讀
普通的select使用快照讀(snapshot read),這是一種不加鎖的一致性讀(Consistent Nonlocking Read),底層使用MVCC來實現
4.4、讀已提交
(1)普通讀是快照讀;
(2)加鎖的select, update, delete等語句,除了在外鍵約束檢查(foreign-key constraint checking)以及重復鍵檢查(duplicate-key checking)時會封鎖區間,其他時刻都只使用記錄鎖;
此時,其他事務的插入依然可以執行,就可能導致,讀取到幻影記錄。
總結
-
並發事務之間相互干擾,可能導致事務出現讀臟,不可重復度,幻讀等問題
-
InnoDB實現了SQL92標准中的四種隔離級別
(1)讀未提交:select不加鎖,可能出現讀臟;
(2)讀提交(RC):普通select快照讀,鎖select /update /delete 會使用記錄鎖,可能出現不可重復讀;
(3)可重復讀(RR):普通select快照讀,鎖select /update /delete 根據查詢條件情況,會選擇記錄鎖,或者間隙鎖/臨鍵鎖,以防止讀取到幻影記錄;
(4)串行化:select隱式轉化為select ... in share mode,會被update與delete互斥;
-
InnoDB默認的隔離級別是RR,用得最多的隔離級別是RC
概括來說,InnoDB實現的RR,通過鎖機制(包含next-key lock)、MVCC(包括數據的隱藏列、基於undo log的版本鏈、ReadView)等,實現了一定程度的隔離性,可以滿足大多數場景的需要。