前言
在大談事務隔離機制前,我們務必要了解 髒讀、不可重複讀、幻讀 。
因為事務隔離機制,就是為了給我們選擇權利去規避髒讀、不可重複讀、幻讀。
如果我們連問題是什麼東西都不清楚,那去了解解決各問題的方案,是不是草率了。
是以,該篇内容主要是想用些通俗易懂的話語結合執行個體去 描述下,
什麼是髒讀?
什麼是不可重複讀?
什麼是幻讀?
正文
一.什麼是髒讀?
舉個例子
我和你的操作分别代表兩個不同的事務操作(送出事務才算完成一個事務所做的事情)。
咱們公用一個錢包(共享經濟),裡面沒有錢。
你 執行一個事務操作,往錢包裡面放入 30塊錢(還未送出) 。
我 執行一個事務操作,查詢 錢包裡面有30塊錢,開心,立刻下訂單,點兩倍奶茶 。
你 神經兮兮地反悔了,放入 30塊錢的事務操作沒有送出(或者復原了)。
我 後面沒有繼續查詢錢包的錢了,一直以為裡面有30塊錢呢, 然後外賣來了, 奶茶是涼的,我也是涼的。
文字描述
事務 A 的未送出(還依然緩存)的資料被 事務 B 讀走,如果 事務 A 失敗復原,會導緻 事務 B 所讀取的的資料是錯誤的。
二.什麼是不可重複讀?
舉個例子
我和你的操作分别代表兩個不同的事務操作。
咱們公用一個錢包(共享經濟),裡面有100塊錢。
我 執行的事務 操作是,先看一眼錢包裡面的錢, 然後跟别人說我的财富是多少多少(直接吹起來了),然後吹完後還看一眼錢包裡面的錢(依依不舍)。 (同一個事務裡面包含兩次查詢,兩次查詢存在間隙)
而你執行 的操作是, 悄咪咪地動了錢包的錢。(修改操作)
場景,
我第一次看錢包裡面的錢, 是100塊, 直接開始自信吹水,我有100塊呢,奶茶随便喝。
我吹的正起勁,你悄咪咪地 取走了錢包裡面的 90塊。
我吹水吹完了,準備再看一眼錢包的錢,結果發現,咦? 怎麼隻有10塊? 我看多了一個零嗎??? 錢包是癟的,我也是癟的。
文字描述
事務A 中 包含 兩次(多次)讀取資料值操作, 而事務B 在A的讀取操作之間 修改資料,導緻事務A 讀取的資料存在不一緻的混亂情況。
三.什麼是幻讀?
舉個例子
我和你的操作分别代表兩個不同的事務操作。
咱們公用一個錢包(共享經濟),原本有100塊錢,然後買奶茶用了30塊,剩下70塊。
大家都能看到 這條消費記錄 : 買奶茶 使用 30元 ,錢包錢數 - 30 元 。
我 執行的事務操作是, 先看一眼 錢包的消費記錄,
(心裡開始計算總額減去每一條消費記錄裡面的錢,剩下多少錢)
然後開始吹我們勤儉節約,開始計劃剩下的錢怎麼用。然後吹完後 還看一眼錢包的消費記錄(依依不舍)。
(同一個事務裡面包含兩次查詢,兩次查詢存在間隙)
你 執行的事務操作是,悄咪咪地消費了幾次,新增了好幾條消費記錄。(新增/删除)
場景,
我第一次看錢包裡面的消費記錄,隻有一條記錄,心裡神算子附身,直接計算出 100塊減去這30塊,那還有70塊~
開始瘋狂吹水,感覺我們很節約,然後還開始計劃後續怎麼動用這筆巨款,計劃表都寫好了。
在我在那叭叭叭吹水和寫計劃表的時候, 你悄咪咪地去消費了幾把, 消費記錄 -10元; -5元 ; -15元;
等我寫完,再去留戀一把,看一下消費記錄,我人傻了。 不是隻有一條資料麼? 怎麼這麼多條???
細細一看,是不是覺得 不可重複讀 和 幻讀 ,這兩個很相似?
确實, 不可重複讀 注重的是 資料值; 而 幻讀 更注重的是 資料集的數量。
也就是說,不可重複讀其實 被影響多是 被 修改操作影響;
而 幻讀 其實 被影響多是 被 新增操作影響(删除目前大多數也隻是一個flag值了)。
Spring事務隔離機制 相比 資料庫事務隔離機制其實也就多一個 default 。
事務隔離級别 | 作用的簡單描述 |
ISOLATION_DEFAULT | 使用後端資料庫預設的隔離級别 |
ISOLATION_READ_UNCOMMITTED | 允許讀取尚未送出的更改。可能導緻髒讀、幻讀或不可重複讀。 |
ISOLATION_READ_COMMITTED | (Oracle 預設級别)允許從已經送出的并發事務讀取。可防止髒讀,但幻讀和不可重複讀仍可能會發生。 |
ISOLATION_REPEATABLE_READ | (MYSQL預設級别)對相同字段的多次讀取的結果是一緻的,除非資料被目前事務本身改變。可防止髒讀和不可重複讀,但幻讀仍可能發生。 |