了解mysql事務隔離機制首先需要理解什麼是acid:
a : 原子性automicity,乙個事務作為不可分割的最小單元,乙個事務裡面的所有操作要麼全部成功,要麼全部失敗。
c:一致性consistency,事物結束後系統狀態是一致的,即 資料不能平白無故的產生,也不能平白無故的消失,例如乙個轉賬業務事務,最終所有賬戶餘額不變。
i:隔離性isolation,簡單的講,乙個事務所有的操作,在最後commit 之前,所有修改對其他事務不可見
d:永續性durability,當事務提交後,資料應該永久被儲存到資料中,即使發生了災難性後果,資料也不會丟失
在實際的運用情況下實現acid是非常困難的,而且效能上也會大打折扣,很多時候不同的業務對事務的要求不一樣,所以為了提公升效能並滿足業務,資料庫提供了4種不同的隔離級別來供使用者選擇
未提交讀(read uncommitted): 這種級別,當乙個事務對資料進行修改後,即使沒有提交,也會被其他事務讀取到,高併發狀態下極易產生髒讀。
已提交讀(read committed):在乙個事務的整個操作過程中,所有的資料修改對其他事務不可見,但這種情況下會導致其他事務中產生不可重複讀(即兩次讀取結果不一致),這個級別也叫作不可重複讀
可重複讀(repeatable read):mysql的預設事務隔離級別,該級別可以保證乙個事務在整個流程中,多次讀取同樣記錄的結果相同,但是沒有解決幻讀的問題。
可序列化(serializable): 是事務最高隔離級別,對同一張表的所有的讀寫都會阻塞,每次都需要獲取表級共享鎖
資料庫的事務隔離越嚴格,併發***越小,但付出的代價也就越大,因為事務隔離實質上就是使事務在一定程度上「序列化」進行,這顯然與「併發」是矛盾的。
同時,不同的應用對讀一致性和事務隔離程度的要求也是不同的,比如許多應用對「不可重複讀"和「幻讀」並不敏感,可能更關心資料併發訪問的能力。
更新丟失:當兩個或多個事務選擇同一行,然後基於最初選定的值更新該行時,由於每個事務都不知道其他事務的存在,就會發生丟失更新問題–最後的更新覆蓋了由其他事務所做的更新。與後面的事務隔離級別無關,因為update、delete 都是更新最新的資料,一般使用樂觀鎖或者悲觀鎖來解決。
髒讀: 事務a讀取到另乙個事務b未提交的修改,事務b回滾修改,那麼事務a就讀取了髒讀。
不可重複讀: 事務a讀取記錄c,在這個過程中事務b將記錄c修改中欄位進行修改,那麼當事務a再次讀取記錄c時,獲取到的結果與第一次不同,叫做不可重複讀。【mvcc版本控制器開解決】
幻讀:幻讀於不可重複讀類似,當事務a第一次讀取某個範圍記錄後,事務b新增了一條記錄,事務a在此讀取這個範圍是會多一條記錄導致幻讀出現【間隙鎖解決幻讀的問題】
隔離級別
髒讀不可重複讀
幻讀未提交讀(read uncommitted)
存在存在
存在已提交讀(read committed)
不存在存在
存在可重複讀(repeatable read)
不存在不存在
存在可序列化(serializable)
不存在不存在
不存在有興趣的同學可以開啟幾個sql命令介面,試一下上面的場景,以下是一些常用的事務處理sql:
select @@tx_isolation; -- 查詢當前隔離機制
begin; -- 開始事務
rollback; -- 回滾
commit; -- 提交
-- 設定當前會話隔離級別
set session transaction isolation level read uncommitted; -- 未提交讀
set session transaction isolation level read committed; -- 已提交讀
set session transaction isolation level repeatable read; -- 可重複讀
set session transaction isolation level serializable; -- 可序列化
-- 設定系統隔離級別
set global transaction isolation level read uncommitted; -- 未提交讀
set global transaction isolation level read committed; -- 已提交讀
set global transaction isolation level repeatable read; -- 可重複讀
set global transaction isolation level serializable; -- 可序列化
spring 事務傳播機制以及隔離級別:
@transactional(rollbackfor = exception.class,isolation = isolation.read_committed)
引數值名稱
解釋isolation. default
default
預設的事務隔離級別,預設是用資料庫的事務隔離級別
isolation. read_uncommitted
未提交讀
髒讀,不可重複讀、幻讀都存在
isolation. read_committed
已提交讀
避免髒讀,但是存在不可重複讀,幻讀
isolation. repeatable_read
可重複讀
避免髒讀和不可重複讀,但是有幻讀的可能
isolation. serializable
序列話避免以上所有讀的問題
例項演示:
新建 user 表,用於演示:
create table `user` (
`id` int not null auto_increment,
`name` varchar(24) default null comment '姓名',
`age` int default null comment '年齡',
primary key (`id`)
) engine=innodb auto_increment=1 default charset=utf8 comment='使用者資訊表';
未提交讀 狀態下的髒讀演示:
- 第一步:開啟事務a、b,並設定鼓勵狀態為 未提交讀。
- 第二步:事務b查詢表結果為空。
- 第三步:事務b插入一條資料,不提交
- 第四步:事務a進行表資料查詢,則查詢到了事務b新增未提交的資料。
- 第五步:事務b回滾提交,造成事務a產生了髒讀。
已提交讀 出現的 不可重複讀 現象:
可重複讀 存在的幻讀可能【幻讀演示,會存在mvcc的影響】:
解釋: 可重複讀的隔離級別下會使用了mvcc機制,當我們執行select操作不會更新版本號,是快照讀(歷史版本);insert、update和delete會更新版本號, 會出現幻讀的情況。為解決 幻讀 的情況 mysql 引入了 間隙鎖,這裡先不做解釋。
注意: 關於 mvcc 和 mysql鎖【間隙鎖】 博主後面的博文會進行解釋。
mysql對映機制 mysql事務隔離機制及其原理
目錄 事務特性acid屬性 併發事務帶來的問題 事務隔離級別 事務實現原理 閒聊 邁莫coding 事務特性acid屬性 事務特性指的就是acid,如圖所示 在這裡插入描述 原子性 atomicity 乙個事務 transaction 中的所有操作,或者全部完成,或者全部不完成,不會結束在中間某個環...
事務隔離機制
五年前在論壇上有過一次提問,如下 下面兩個問題的答案就是資料庫的事務隔離機制。資料庫針對外部的併發請求,也是要考慮資源搶占問題的,所以資料庫針對同一記錄的寫請求,也是要加鎖的!最簡單的方式就是針對每個請求都加鎖,全部序列,這樣肯定不會有問題。但這樣效能很低,所以db將鎖分為了讀鎖和寫鎖,也就是常說的...
Mysql 中的事務隔離機制
0.read uncommitted 可以讀未提交事務資料 髒讀 1.read committed 只可以讀提交事務資料 不可重複讀 2.repeatable read 只有兩個事務都提交,才可以讀到新資料 幻讀 3.serializable 只有乙個事務可以運算元據,無論讀寫,其他事務等待 set...