03 事務伴生源 Isolation

2021-10-11 01:56:03 字數 3706 閱讀 2053

二 擊穿隔離級別

三 不可重複讀和幻讀的區別

四 悲觀鎖和樂觀鎖

當兩個事務對同乙個資料庫的記錄進行操作時,那麼,他們之間的影響是怎麼樣的呢? 這就出現了事務隔離級別的概念。

資料庫的隔離性與併發控制有很大關係。資料庫的隔離級別是資料庫的事務特性acid的一部分。acid,即原子性(atomicity)、一致性(consistency)、隔離性(isolation) 和 永續性(durability).

事務隔離級別分為: read_uncommitted 讀未提交, read_committed 讀提交, repeatable_read 可重複讀, serializable序列化.

default(不同的資料庫不同的預設隔離級別,mysql預設為repeatable_read).

隔離級別/事務缺陷

髒讀不可重複讀

幻讀read_uncommitted√√

√read_committed√√

repeatable_read

√serializable

1、read_uncommitted

​ 事務a讀取到事務b insert 而未提交的資料,b回滾,造成a事務髒讀(dirty read) 等

2、read-committied

​ 事務a讀取資料,b事務修改資料,事務a再次讀取資料,造成兩次讀取資料不一致,造成不可重複讀(non-repeated read)

3、repeatable_read

​ 事務a兩次或多次讀取一系列記錄,期間事務b insert 一條記錄,事務a多次讀取的一系列記錄不一致,造成幻讀****(phantom read)

4、serializable

​ 所有事務的read 和 write 都上鎖,序列執行。但效能會下降。

顧名思義,read_uncommitted意思是,乙個事務可以讀取到另乙個事務未提交的事務記錄。換句話說,a transaction canreadthe data that is stilluncommittedby other transactions。

這是spring事務最弱的隔離級別。見下面的圖,事務a開啟,寫入一條記錄,這時候,事務b讀入資料,讀到了這條記錄,但是,之後事務a回滾。因此,事務b讀到的資料不是有效的(the database is in an invalid state)。這種情況稱為髒讀(dirty read)。除了髒讀的問題,read_uncommitted還可能出現non-repeatable read(不可重複讀)phantom read(幻讀)的問題。

read_committed隔離級別表明,乙個事務只能讀取到已經提交的記錄,不能讀取到未提交的記錄。換句話說,a transaction can onlyreadthecommitteddata, and it can』t read the uncommitted data. 因此,dirty read的情況不再發生,但可能會出現其他問題。見下圖。

在事務a兩次讀取的過程之間,事務b修改了那條記錄並進行提交。因此,事務a前後兩次讀取的記錄不一致。這個問題稱為non-repeatable read(不可重複讀)。(兩次讀取的記錄不一致,重複讀取就會發現問題。) 除了non-repeatable read的問題,read_committed還可能發生phantom read的問題。

repeatable_read意思是,乙個事務可以多次從資料庫讀取某條記錄,而且多次讀取的那條記錄都是一致的,相同的。這個隔離級別可以避免dirty read和non-repeatable read的問題,但可能發生phantom read的問題。如下圖:

事務a兩次從資料庫讀取**一系列記錄,期間,事務b插入了某條記錄並提交。事務a第二次讀取時,會讀取到事務b剛剛插入的那條記錄。在事務期間,事務a兩次讀取的一系列記錄不一致,這個問題稱為phantom read**。

serializable是spring最強的隔離級別。事務執行時,會在所有級別上加鎖,比如read和write時都會加鎖,彷彿事務是以序列的方式進行的,而不是一起發生的。這會防止 dirty read、non-repeatable read 和 phantom read 的出現,但是,會帶來效能的下降。

行鎖和表鎖的區別

如果或者刪除一條資料,加上行鎖;就可避免其他事務的不可重複讀.

但是如果增加一條資料,行鎖對於新來的夥計(insert的資料)不起作用,這時表鎖可以解決此類問題

這裡可以衍生出對這兩者的其他區別:

如: 不可重複讀針對delete/update操作, 幻讀針對insert操作

所以說不可重複讀和幻讀最大的區別,就在於如何通過鎖機制來解決他們產生的問題。

這裡說的,是使用悲觀鎖機制來處理這兩種問題,但是mysql、oracle、postgresql等成熟的資料庫,出於效能考慮,都是使用了以樂觀鎖為理論基礎的mvcc(多版本併發控制)來避免這兩種問題。

####悲觀鎖和樂觀鎖####

正如其名,它指的是對資料被外界(包括本系統當前的其他事務,以及來自外部系統的事務處理)修改持保守態度,因此,在整個資料處理過程中,將資料處 於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機 制,也無法保證外部系統不會修改資料)。

在悲觀鎖的情況下,為了保證事務的隔離性,就需要一致性鎖定讀。讀取資料時給加鎖,其它事務無法修改這些資料。修改刪除資料時也要加鎖,其它事務無法讀取這些資料。

相對悲觀鎖而言,樂觀鎖機制採取了更加寬鬆的加鎖機制。悲觀鎖大多數情況下依靠資料庫的鎖機制實現,以保證操作最大程度的獨占性。但隨之而來的就是資料庫效能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。

而樂觀鎖機制在一定程度上解決了這個問題。樂觀鎖,大多是基於資料版本( version )記錄機制實現。何謂資料版本?即為資料增加乙個版本標識,在基於資料庫表的版本解決方案中,一般是通過為資料庫表增加乙個 「version」 欄位來實現。讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交資料的版本資料與資料庫表對應記錄的當前版本資訊進行比對,如 果提交的資料版本號大於資料庫表當前版本號,則予以更新,否則認為是過期資料。

要說明的是,mvcc(multi-version concurrency control)的實現沒有固定的規範,每個資料庫都會有不同的實現方式,這裡討論的是innodb的mvcc。mvcc 下面章節會講到

MySQL03 多表 事務

有兩個集合a,b 取這兩個集合的所有組成情況。要完成多表查詢,需要消除無用的資料 1.2.1 內連線查詢 1.隱式內連線 使用where條件消除無用資料 2.顯式內連線 1 select 字段列表 from 表名1 inner join 表名2 on 條件 3.內連線查詢總結 1.從哪些表中查詢資料...