Mysql事務隔離級別和鎖機制

2022-07-25 11:54:19 字數 4444 閱讀 3678

一.spring支援四種事務隔離級別:

1.isolation_read_uncommitted(讀未提交):這是事務最低的隔離級別,它充許令外乙個事務可以看到這個事務未提交的資料。

2.isolation_read_committed(讀已提交): 保證乙個事務修改的資料提交後才能被另外乙個事務讀取。另外乙個事務不能讀取該事務未提交的資料

3.isolation_repeatable_read(可重複讀): 這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻像讀。

4.isolation_serializable(可序列化) 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。

spring設定中還有乙個預設級別:

isolation_default:使用資料庫預設的事務隔離級別。

二、一些名詞

多個事務併發會產生一些問題:

髒讀:可以讀取到其他事務修改但未提交的髒資料。

不可重複讀:在乙個事務中重複讀取相同資料。在其中兩次讀取資料之間有另乙個事務修改並提交了該資料。使得事務兩次讀到的資料是不一樣的。

幻讀:第乙個事務對乙個表中的資料進行了修改,這種修改涉及

到表中的全部資料行。同時,第二個事務也修改這個表中的資料,這種修改是向表中插入一行新資料。那麼,以後就會發生操作第乙個事務的使用者發現表中還有沒有

修改的資料行,就好象發生了幻覺一樣。

丟失更新:多個使用者同時對乙個資料資源進行更新,必定會產生被覆蓋的資料,造成資料讀寫異常

。例子:假定有資料表

==student==

id | name

1  | 張三

a.髒讀

事務a:select name from student where id=1;

事務b:update  student set name='李四' where id=1;不提交

結果:可能是「李四」

讀已提交:避免讀取未提交資料。

b.不可重複讀

事務a:select name from student where id=1;

select name from student where id=1;

事務b:update  student set name='李四' where id=1;提交

結果:第一次讀到「張三」,第二次可能讀到「李四」

可重複讀:避免事務b修改id為1的資料。但是事務b可以向表中新增資料李四

c.幻讀

事務a:select name from student;

select name from student;

事務b:insert into student values(default,'李四');提交

結果:第一次讀到「張三」,第二次可能讀到"張三"和"李四"

序列化讀:每次讀都需要獲得表級共享鎖,讀寫相互都會阻塞。可避免幻讀。

各種隔離級別與各種讀的關係:

三、mysql預設隔離級別

mysql/innodb預設是可重複讀的(repeatable read);

oracle預設隔離級別是讀已提交(read_committed);

四、修改與查詢mysql事務隔離級別的方法:

1

#查全域性事務隔離級別

2select @@global.tx_isolation;

3#查當前會話事務隔離級別

4select @@session.tx_isolation;

5#查當前事務隔離級別

6select @@tx_isolation;

7#設定全域性隔離級別

8set

global

transaction isolation level read committed;

9#設定當前會話隔離級別

10set session transaction isolation level read committed;

其它隔離級別的設定就不說了。

測試,以root身份登陸,修改session.tx_isolation:

退出mysql,再次以root身份登陸,上次會話的設定失效:

更換身份,使用foreigner身份登陸,修改全域性許可權:

再次以root身份登陸,檢視許可權:

可見,全域性事務隔離級別是mysql全域性的,與某個使用者的或者某個會話的隔離級別沒有關係。

五、鎖機制

定義:當有事務操作時,資料庫引擎會要求不同型別的鎖定,如相關資料行、資料頁或是整個資料表,當鎖定執行時,會阻止其他事務對已經鎖定的資料行、資料頁或資料表進行操作。只有在當前事務對於自己鎖定的資源不在需要時,才會釋放其鎖定的資源,供其他事務使用。

我個人對鎖的理解是,某執行緒想要執行某個事務中的某條sql,必須得有某個鎖。如果沒有該鎖,要等待自己獲得該鎖後才能執行相應操作。

共享鎖(share)

共享鎖的代號是s,共享鎖的鎖粒度是行或者元組(多個行)。乙個事務獲取了共享鎖之後,可以對鎖定範圍內的資料執行讀操作。

排它鎖(exclusive)

排它鎖的代號是x,是exclusive的縮寫,排它鎖的粒度與共享鎖相同,也是行或者元組。乙個事務獲取了排它鎖之後,可以對鎖定範圍內的資料執行寫操作。

意向鎖

意向鎖的含義是如果對乙個結點加意向鎖,則說明該結點的下層結點正在被加鎖;對任一結點加鎖時,必須先對它的上層結點加意向鎖。如:對錶中的任一行加鎖時,必須先對它所在的表加意向鎖,然後再對該行加鎖。這樣一來,事務對錶加鎖時,就不再需要檢查表中每行記錄的鎖標誌位了,系統效率得以大大提高。

簡單的說就是我要對哪個表進行事務操作了,就給哪個表加乙個意向鎖。

鎖的互斥與相容關係

鎖和鎖之間的關係,要麼是相容的,要麼是互斥的。

鎖a和鎖b相容是指:操作同樣一組資料時,如果事務t1獲取了鎖a,另乙個事務t2還可以獲取鎖b;

鎖a和鎖b互斥是指:操作同樣一組資料時,如果事務t1獲取了鎖a,另乙個事務t2在t1釋放鎖a之前無法獲取鎖b。

上面提到的共享鎖、排它鎖、意向共享鎖、意向排它鎖相互之前都是有相容/互斥關係的,可以用乙個相容性矩陣表示(y表示相容,n表示互斥):

六、悲觀鎖和樂觀鎖

悲觀鎖(pessimistic lock), 每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。

樂觀鎖(optimistic lock), 每次去拿資料的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個資料,可以使用版本號等機制。樂觀鎖適用於多讀的應用型別,這樣可以提高吞吐量,像資料庫如果提供類似於write_condition機制的其實都是提供的樂觀鎖。

兩種鎖各有優缺點,不可認為一種好於另一種,像樂觀鎖適用於寫比較少的情況下,即衝突真的很少發生的時候,這樣可以省去了鎖的開銷,加大了系統的整個吞吐量。但如果經常產生衝突,上層應用會不斷的進行retry,這樣反倒是降低了效能,所以這種情況下用悲觀鎖就比較合適。

七、丟失更新及解決方法。

丟失更新:

假設沒有x鎖存在。執行a,b兩個事務。下面這種情況事務a的提交會被事務b的提交覆蓋

解決辦法,加入x鎖即可。

mysql 鎖 事務隔離級別

最近在看mysql相關的書籍.實驗了一些內容.分享一下,主要是關於事務隔離級別 read committed和repeatable read 和鎖相關的.很多網上文章上都能搜尋到 read committed可以防止髒資料.但是不能防止 不可重複讀.而repeatable read可以防止 不可重複...

MySQL的事務隔離級別和鎖

mysql的事務隔離級別 read uncommitted 讀未提交資料 read committed 讀已提交資料 repeatable read 可重讀 serializable 可序列化 檢視mysql的事務隔離級別 預設 全域性和會話事務隔離級別 select tx isolation se...

mysql鎖問題 事務隔離級別

相對其他資料庫而言,mysql的鎖機制比較簡單,其最顯著的特點是不同的儲存引擎支援不同的鎖機制。innodb最大的特點就是一是支援事務 transaction 二是採用了行級鎖。所以我們先來引申一下事務和事務隔離級別的知識。1.1 事務以及acid屬性 事務是由一組sql語句組成的邏輯處理單元,事務...