1. 程式人生 > >事務隔離級別、傳播行為及鎖機制

事務隔離級別、傳播行為及鎖機制

1、事務的特性

    事務具備以下四個特性,簡稱ACID屬性。

  原子性(Atomicity):

    事務是一個完整的操作,事務的各步操作都是不可再分的,要麼都執行, 要麼都不執行。

  一致性(Consistency):

    當事務完成時,資料必須處於一致的狀態。

  隔離性(Isolation):

    併發事務之間相互獨立、隔離,它不應以任何方式依賴於或影響其他事 務。

  永續性(Durability):

    事務完成後,它對資料庫的修改被永久保持。

2、 事務的隔離級別 

       

  ① Read uncommitted (讀未提交):最低級別,任何情況都無法保證。

  ② Read committed (讀已提交):可避免髒讀的發生。

  ③ Repeatable read (可重複讀):可避免髒讀、不可重複讀的發生。

  ④ Serializable (序列化):可避免髒讀、不可重複讀、幻讀的發生。

3、 髒讀、不可重複讀、幻讀

  ①髒讀

    髒讀是指在一個事務處理過程裡讀取了另一個未提交的事務中的資料。

  ②不可重複讀

    不可重複讀是指在對於資料庫中的某個資料,一個事務範圍內多次查詢卻返回了不同的資料值,這是由於在查詢間隔,被另一個事務修改並提交了。

  ③虛讀(幻讀)

    幻讀是事務非獨立執行時發生的一種現象。例如事務T1對一個表中所有的行的某個資料項做了從“1”修改為“2”的操作,這時事務T2又對這個表中插入了一行資料項,而這個資料項的數值還是為“1”並且提交給資料庫。而操作事務T1的使用者如果再檢視剛剛修改的資料,會發現還有一行沒有修改,其實這行是從事務T2中新增的,就好像產生幻覺一樣,這就是發生了幻讀。

4、 事務的七種傳播行為

  什麼是事務的傳播行為:事務傳播行為用來描述由某一個事務傳播行為修飾的方法被巢狀進另一個方法的時事務如何傳播。

 

事務傳播行為型別

說明

PROPAGATION_REQUIRED

如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。

PROPAGATION_SUPPORTS

支援當前事務,如果當前沒有事務,就以非事務方式執行。

PROPAGATION_MANDATORY

使用當前的事務,如果當前沒有事務,就丟擲異常。

PROPAGATION_REQUIRES_NEW

新建事務,如果當前存在事務,把當前事務掛起。

PROPAGATION_NOT_SUPPORTED

以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

PROPAGATION_NEVER

以非事務方式執行,如果當前存在事務,則丟擲異常。

PROPAGATION_NESTED

如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

5、鎖機制

  悲觀鎖:

    總是假設最壞的情況,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會阻塞直到它拿到鎖(共享資源每次只給一個執行緒使用,其它執行緒阻塞,用完後再把資源轉讓給其它執行緒)。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。Java中synchronized和ReentrantLock等獨佔鎖就是悲觀鎖思想的實現。 

  樂觀鎖:(不能解決髒讀的問題)

    總是假設最好的情況,每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號機制或CAS演算法實現。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,像資料庫提供的類似於write_condition機制,其實都是提供的樂觀鎖。在Java中java.util.concurrent.atomic包下面的原子變數類就是使用了樂觀鎖的一種實現方式CAS實現的。

  Mysql InnoDB引擎的鎖機制(屬於悲觀鎖)

  (之所以以InnoDB為主介紹鎖,是因為InnoDB支援事務,支援行鎖和表鎖用的比較多,Myisam不支援事務,只支援表鎖)

   1)按照鎖的使用方式可分為:共享鎖、排它鎖、意向共享鎖、意向排他鎖

    共享鎖/讀鎖(S):允許一個事務去讀一行,阻止其他事務獲得相同資料集的排他鎖。(其他事務可以讀但不能寫該資料集) 

    排他鎖/寫鎖(X):允許獲得排他鎖的事務更新資料,阻止其他事務取得相同資料集的共享讀鎖和排他寫鎖。 (其他事務不能讀和寫該資料集)

    意向共享鎖(IS):通知資料庫接下來需要施加什麼鎖並對錶加鎖。如果需要對記錄A加共享鎖,那麼此時innodb會先找到這張表,對該表加意向共享鎖之後,再對記錄A新增共享鎖。

    意向排他鎖(IX):通知資料庫接下來需要施加什麼鎖並對錶加鎖。如果需要對記錄A加排他鎖,那麼此時innodb會先找到這張表,對該表加意向排他鎖之後,再對記錄A新增排他鎖。

注:

  A、意向共享鎖和意向排它鎖是資料庫主動加的,不需要我們手動處理;

  B、對於UPDATE、DELETE和INSERT語句,InnoDB會自動給涉及資料集加排他鎖(X);對於普通SELECT語句,InnoDB不會加任何鎖,事務可以通過以下語句顯示給記錄集加共享鎖或排他鎖。

  共享鎖(S):SELECT * FROM table_name WHERE … LOCK IN SHARE MODE。

  排他鎖(X):SELECT * FROM table_name WHERE … FOR UPDATE。

 

  2)按照鎖的粒度可分為:行鎖、頁鎖(間隙鎖)、表鎖

    行鎖是通過給索引上的索引項加鎖來實現的,只有通過索引條件來檢索資料才會用到行鎖,否則InnoDB將會使用表鎖。

    表鎖:select * from table_nane where name = ‘小巷’  for update 。name欄位不是唯一索引欄位,所以是表鎖。(表排他鎖)

    行鎖:select * from table_name where  id = 1 for update 。id 欄位為唯一索引欄位,所以使用的就是行鎖,且是排它鎖。

    頁鎖(又叫Gap鎖/間隙鎖):所謂表鎖鎖表,行鎖鎖行,那麼頁鎖折中,鎖相鄰的一組資料。

 

  通過加鎖控制,可以保證資料的一致性,但是同樣一條資料,不論用什麼樣的鎖,只可以併發讀,並不可以讀寫併發(因為寫的時候加的是排他鎖所以不可以讀),這時就要引入資料多版本控制來實現讀寫併發。

 

  MVCC(資料多版本併發控制,屬於樂觀鎖)

    這項技術使得InnoDB的事務隔離級別下執行一致性讀操作有了保證,換言之,就是為了查詢一些正在被另一個事務更新的行,並且可以看到它們被更新之前的值。這是一個可以用來增強併發性的強大的技術,因為這樣的一來的話查詢就不用等待另一個事務釋放鎖。

&n