本文章主要解釋以下主要幾個問題:
事物與ACID屬性:
- 原子性(Atomicity)
- 一致性(Consistent)
- 隔離性(Isolation)
- 持久性(Durable)
并發(fā)事物處理帶來的問題
- 更新丟失
- 臟讀
- 不可復讀
- 幻讀
事物與ACID屬性:
1瑟押、原子性 Atomicity
事務的原子性指的是,事務中包含的程序作為數據庫的邏輯工作單位颜曾,它所做的對數據修改操作要么全部執(zhí)行鼠锈,要么完全不執(zhí)行。這種特性稱為原子性耕腾。
2愤炸、一致性 Consistency
事務的一致性指的是在一個事務執(zhí)行之前和執(zhí)行之后數據庫都必須處于一致性狀態(tài)筋现。這種特性稱為事務的一致性拴竹。假如數據庫的狀態(tài)滿足所有的完整性約束悟衩,就說該數據庫是一致的。
3栓拜、隔離性 Isolation
隔離性指并發(fā)的事務是相互隔離的座泳。即一個事務內部的操作及正在操作的數據必須封鎖起來,不被其它企圖進行修改的事務看到菱属。
4钳榨、持久性 Durability
持久性意味著當系統(tǒng)或介質發(fā)生故障時,確保已提交事務的更新不能丟失纽门。即一旦一個事務提交,DBMS保證它對數據庫中數據的改變應該是永久性的营罢,耐得住任何數據庫系統(tǒng)故障赏陵。持久性通過數據庫備份和恢復來保證。
這里不對ACID做過多的解釋饲漾,大學課本里面有的
數據庫表的創(chuàng)建及數據插入見文末
行鎖重現
這里分為事物A與事物B蝙搔,模擬多線程操作環(huán)境
事物A
begin
--開啟一個事物Aupdate account set balance =3000 where id=3;
-- 更新id=3 余額此時事物中Seesion中id=3余額已經修改為3000
事物A掛起,事物B進入
此時事物B提交等待考传,應為事物A對id=3的行進行操作并未提交吃型,過一段時間后會顯示超時
這段時間如果事物A提交,事物B也會隨即提交
并發(fā)事物處理帶來的問題:
- 更新丟失: 兩個事物同事操作相同的數據僚楞,后提交的事物會先覆蓋先提交的事物處理結果通過樂觀鎖就可以解決
- 臟讀: 事物A讀取到了事物B以及修改單尚未提交的數據勤晚,如果事物B回滾,A讀取的數據無效泉褐,不符合一致性
- 不可復讀: 事物A讀取到了事物B已經提交的修改數據赐写,不符合隔離性
- 幻讀 : 事物A讀取帶了事物B提交的新增數據,不符合隔離性
更新丟失和臟讀是非常容易理解的膜赃,這里解釋一下不可復讀挺邀,
不可復讀:事物A先從數據庫查詢到變量a=2,此時事物B修改a=3并且提交,然后事物A查詢變量a的值應該為多少呢端铛?
不可復讀指的就是事物A讀到a=3.開始事物A操作都是基于a=2,
事物B修改后a=3;此時肯定會出錯泣矛,事物A操作都是基于賬號2,但是后面卻事物B介入禾蚕。
這樣就代碼沒辦法去寫以一定漏洞百出
幻讀:與不可復讀類似乳蓄,事物A讀數據庫中只有一條數據,事物B將這條記錄刪除夕膀,此時事物A再去讀表中將不會有記錄虚倒。這樣數據庫邏輯不符合,無法進行
四種事物隔離級別
下面進行實列驗證
- Mysql默認事物隔離級別是REPRATABLE-READ(可從重復讀)
數據庫事物常用命令
--開啟事務
begin产舞;
--顯示數據庫事物隔離級別
show variables like 'tx_isolation';
--設置數據庫事物隔離級別
set tx_isolation ='REPRATABLE-READ'魂奥;
--提交事物
commit;
--回滾
roolback易猫;
- 1 耻煤、臟讀
藍色框執(zhí)行順序無要求,黃色框按照指定順序執(zhí)行
對應步驟的執(zhí)行結果下圖:
- 2准颓、不可復讀
幻讀.png
藍色框執(zhí)行順序無要求哈蝇,黃色框按照指定順序執(zhí)行
對應步驟的執(zhí)行結果下圖:幻讀-1.jpg
在此邏輯情況下肯定也會出現問題,假設一個線程A先讀取到balance的值400攘已,根據自己邏輯情況下Java將該值設為100炮赦;那么此時數據邏輯該怎么進行的!操作都是基于400样勃,一段時間后卻變?yōu)榱?50.
- 3吠勘、不可復讀
幻讀.png
藍色框執(zhí)行順序無要求,黃色框按照指定順序執(zhí)行
Mysql數據庫默認的隔離級別就是“可重復讀”峡眶,所以此時為進行set
對應步驟的執(zhí)行結果下圖:
幻讀-111.jpg
幻讀現象肯定也是不符合業(yè)務邏輯的剧防,比如事物A讀取到賬戶1,并且基于賬戶A操作辫樱,此時另外一個線程介入開啟另外一個事物并刪除了1(或者新增了賬戶)峭拘,此時另外事物A基于賬戶1操作,半途卻發(fā)現一個賬戶都沒有咯狮暑。 - 4 鸡挠、可串行化就是前面幾種情況都不會出現,相當于加入一把大鎖心例,業(yè)務進入即將表鎖定宵凌。但是效率極低,所以數據庫一般采用的可重復讀級別
MVCC機制:此時同一個事物在執(zhí)行第一次的Select時候回建立一個快照止后,在此查詢是會讀取到快照的瞎惫。鎖幻讀情況的重現會出現問題溜腐,先執(zhí)行一次update事物B新增的,再次進行select時候就能出現幻讀
表創(chuàng)建sql
CREATE TABLE account(
id int(11) NOT NULL AUTO_INCREMENT,
name VARCHAR (255) DEFAULT NULL,
balabce INT(11) DEFAULT NULL,
PRIMARY KEY(id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT into account(name,balance)VALUES("李雷","450");
INSERT into account(name,balance)VALUES("韓梅梅","16000");
INSERT into account(name,balance)VALUES("lucy","2400");