《金三銀四》面試官:說說事務的ACID,什麼是髒讀、幻讀?

1、事務

事務是數據庫管理系統執行過程當中的一個邏輯單位,由一個有限的數據庫操做序列構成。--摘自百科java

在MySQL裏,事務是在引擎層面實現,好比MyIsam不支持,InnoDB支持mysql

2、ACID

提到事務,確定會想到 ACID 是吧,自行感覺一下概念,而後咱們來說講隔離性的問題。面試

  • 原子性:事務的全部操做要麼所有成功,要麼所有回滾。sql

  • 在這裏插入圖片描述

  • 一致性:老是從一個一致性的狀態轉換到另外一個一致性的狀態。數據庫

  • 隔離性:多個事務併發執行時,一個事務的執行不該影響其餘事務的執行 session

    在這裏插入圖片描述

  • 持久性:已被提交的事務對數據庫的修改應該永久保存在數據庫中。併發

3、隔離級別

作了多年的 CRUDer,對這幾個詞真是不陌生,要不是出去面試,也真不會去了解。但願你們看完以後,面試的時候,不要慌,跟他剛。測試

實際上,這些場景都是出如今多個事務同時執行時的場景。spa

3.1 髒讀(Read Uncommitted)

通俗的講,一個事務在處理過程當中讀取了另一個事務未提交的數據。code

你都還沒提交,我就讀到了你剛操做的數據,萬一你回滾了怎麼辦,你說這髒不髒。

舉例:

在這裏插入圖片描述

假設打賞的邏輯是:① 個人帳戶+1元;② 你的帳戶-1元。

當你執行到第一個步驟,我去查詢個人帳戶已是2元了,很開心!!!宣佈請你們去擼串!!!可是最後扣款的時候發現你餘額不足了,回滾了,個人1元沒了,就很難受!!

3.2 不可重複讀(Non-repeatable Read)

通俗的講,一個事務範圍內,屢次查詢某個數據,卻獲得不一樣的結果。

與髒讀的區別:髒讀是讀到未提交的數據,而不可重複讀讀到的倒是已經提交的數據,但其實是違反了事務的一致性原則。

舉例:

在這裏插入圖片描述

假設我查了下帳戶餘額,看到大家給小編打賞了1塊錢,很開心!!!宣佈請你們去擼串!!!在付款以前,錢被另一我的取走,又查詢到沒錢了,被留下來洗碗了!!!

由於我查詢完後,這條數據沒鎖住,又被別的事務更新了,致使當前事務每次都是讀到最新的數據。

3.3 幻讀

在Repeatable Read隔離級別下,一個事務可能會遇到幻讀(Phantom Read)的問題。

事務A讀取與搜索條件相匹配的若干行。事務B以插入或刪除行等方式來修改事務A的結果集,而後再提交。

舉例:

在這裏插入圖片描述
看到了嗎,在一個事務A中,第一次查詢某條記錄,是沒有的,可是,當試圖更新這條不存在的記錄時,居然能成功,而且,再次讀取同一條記錄,它就神奇地出現了。

實際上,在InnoDB引擎中,對於索引的掃描,不只鎖住掃描到的索引,並且還鎖住這些索引覆蓋的範圍(gap),所以這個範圍是內插入數據是不容許的。

4、mysql模擬事務隔離性測試

SELECT @@session.tx_isolation;   
SELECT @@tx_isolation;  
  
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;  

start transaction;

--建表
drop table AMOUNT;
CREATE TABLE `AMOUNT` (
`id`  varchar(10) NULL,
`money`  numeric NULL
)
;
--插入數據
insert into amount(id,money) values('A', 800);
insert into amount(id,money) values('B', 200);
insert into amount(id,money) values('C', 1000);
--測試可重複讀,插入數據
insert into amount(id,money) values('D', 1000);

--設置事務
SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted;  
SELECT @@tx_isolation;  
--開啓事務
start transaction;

--髒讀演示,讀到其餘事務未提交的數據
--案列1,事務一:A向B轉200,事務二:查看B金額變化,事務一回滾事務
update amount set money = money - 200 where id = 'A';
update amount set money = money + 200 where id = 'B';

--不可重複讀演示,讀到了其餘事務提交的數據
--案列2,事務一:B向A轉200,事務二:B向C轉200100
SET SESSION TRANSACTION ISOLATION LEVEL read committed;  

--開啓事務
start transaction;
--兩個事務都查一下數據(轉帳以前須要,查一下金額是否夠知足轉帳)
select * from amount;
--事務一:B向A轉200
update amount set money = money - 200 where id = 'B';
update amount set money = money + 200 where id = 'A';

commit;
--事務二:B向C轉200100
update amount set money = money - 100 where id = 'B';
update amount set money = money + 100 where id = 'C';
commit;
--從事務二的角度來看,讀到了事務一提交事務的數據,致使金額出現負數

--幻讀演示
--案列3,事務一:B向A轉200,事務二:B向C轉200100
SET SESSION TRANSACTION ISOLATION LEVEL repeatable read;  

--開啓事務
start transaction;
--兩個事務都查一下數據(轉帳以前須要,查一下金額是否夠知足轉帳)
select * from amount;
--事務一:B向A轉200
update amount set money = money - 200 where id = 'B';
update amount set money = money + 200 where id = 'A';

commit;
--事務二:B向C轉200100
update amount set money = money - 100 where id = 'B';
update amount set money = money + 100 where id = 'C';
commit;
--從事務二的角度來看,讀到了事務一提交事務的數據,致使金額出現負數

複製代碼

相關文章
相關標籤/搜索