事務(wù)是邏輯上的一組操作,組成這組操作的各個單元,要不全都成功要不全都失敗,這個特性就是事務(wù),下面就是關(guān)于MySQL事務(wù)學(xué)習(xí)中的心得分享:
事務(wù)的特性
1.原子性(Atomicity):原子性是指事務(wù)是一個不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
2.一致性(Consistency):在一個事務(wù)中,事務(wù)前后數(shù)據(jù)的完整性必須保持一致,可以想象銀行轉(zhuǎn)賬、火車購票。
3.隔離性(Isolation):多個事務(wù),事務(wù)的隔離性是指多個用戶并發(fā)訪問數(shù)據(jù)庫時, 一個用戶的事務(wù)不能被其它用戶的事務(wù)所干擾,多個并發(fā)事務(wù)之間數(shù)據(jù)要相互隔離。
4.持久性(Durability):持久性是指一個事務(wù)一旦被提交,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫發(fā)生故障也不應(yīng)該對其有任何影響。
寫這些概念呢,是有點繞!繞就繞吧!反正也不是我規(guī)定的,這是官方的,解釋是我編的?。?!
事務(wù)的并發(fā)訪問問題
如果我們在不考慮隔離性問題時,事務(wù)是存在三種并發(fā)訪問問題的。
1.臟讀:在一個事務(wù)中,當(dāng)讀取數(shù)據(jù)時,讀到了另一個事務(wù)未提交的數(shù)據(jù)。
比如A賬戶給B賬戶轉(zhuǎn)了1塊錢,但是A沒有提交事務(wù),被B賬戶通過臟讀看到了,這時,B就會以為A已經(jīng)把錢轉(zhuǎn)過來了,但是這時,A賬戶回滾事務(wù)。其實錢就沒給B轉(zhuǎn)過去,但是B自己本身以為A已經(jīng)轉(zhuǎn)過去了,,,有點繞,估計是我描述到繞!
看代碼:
update account set money=money+1 where name='B'; --此時A去通知B
update account set money=money -1 where name='A';
2.不可重復(fù)讀:在一個事務(wù)中,兩次讀取的數(shù)據(jù)內(nèi)容不一致,這是因為在查詢時,有時間間隔,數(shù)據(jù)被另一個事務(wù)已經(jīng)修改提交了,那就會出現(xiàn)問題。
3.幻讀/虛讀:在一個事務(wù)中,兩次讀取的數(shù)據(jù)量不一致。
事務(wù)的隔離級別
上面介紹了3種事務(wù)并發(fā)問題!現(xiàn)在介紹一下數(shù)據(jù)庫提供的解決方案!
1.read uncommitted : 讀取尚未提交的數(shù)據(jù) :這個最低級,但是效率肯定最高,但是哪一個問題都不能解決。
2.read committed:讀取已經(jīng)提交的數(shù)據(jù) :可以解決臟讀 。
3.repeatable read:重讀讀?。嚎梢越鉀Q臟讀 和 不可重復(fù)讀 。
4.serializable:串行化:可以解決臟讀不可重復(fù)讀和虛讀,效率最差,相當(dāng)于鎖表,開發(fā)中一般不用。
上面的“2”是oracle數(shù)據(jù)庫默認設(shè)置,“3”是mysql數(shù)據(jù)庫默認的設(shè)置。
下面呢我就重點解釋一下mysql數(shù)據(jù)庫在上面各種事務(wù)隔離級別上的演示:
首先介紹兩個語法:
1.查看mysql數(shù)據(jù)庫默認的隔離級別:select @@tx_isolation
如圖:
![](/d/20211018/9eaf1543703d7888d2cb1d0853936c7e.gif)
2.設(shè)置mysql的隔離級別:set session transaction isolation level 事務(wù)的隔離級別
如圖:
![](/d/20211018/6090876a87de3b05390d5a5676dfb063.gif)
事務(wù)的隔離級別演示
注意:如果要自己模擬要開啟兩個mysql客戶端,也就是模擬兩個用戶!
1.read uncommitted
如圖:
![](/d/20211018/6090876a87de3b05390d5a5676dfb063.gif)
我通過語法將數(shù)據(jù)庫的事務(wù)隔離級別改為了read uncommitted。
首先我有一張account表。
如圖:窗口一
![](/d/20211018/9b4d1cfa33e0a4ebe8cff34368fa617f.gif)
窗口二
![](/d/20211018/ae499d7cdb84aec65f0c6c5a716fd772.gif)
數(shù)據(jù)庫表原始數(shù)據(jù)money都是5000,當(dāng)我啟動事務(wù)后,在zhangsan賬戶增加了1000和在李四賬戶減去了1000,但是我的事務(wù)還未提交,但是我再次查詢數(shù)據(jù)庫表時,數(shù)據(jù)已經(jīng)發(fā)生變化,這就是臟讀和不可重復(fù)讀!
幻讀/虛讀我就不掩飾了,同樣存在!
2.read committed
如圖:
![](/d/20211018/4edfb56f8b39ea5437da23cd066daf88.gif)
我將數(shù)據(jù)庫事務(wù)隔離性改為了read committted。
還是上面那張表:
如圖:窗口一
![](/d/20211018/9f80bb2fc32492bcab06741b983aecdc.gif)
窗口二
![](/d/20211018/792c7f41d0054a2678e4f1e3ecaca1a9.gif)
數(shù)據(jù)庫表zhangsan賬戶的money和lisi賬戶的money都發(fā)生了變化,我未提交事務(wù),在另一個窗口事務(wù)開啟下查詢時,沒有出現(xiàn)臟讀,但是當(dāng)我提交事務(wù)時,在另一個窗口的事務(wù)下再次查詢,出現(xiàn)了不可重復(fù)讀的情況,這樣可以避免臟讀,但是查詢時已經(jīng)出現(xiàn)不可重復(fù)讀和幻讀/虛讀!
3.repeatable read
如圖:
![](/d/20211018/2c7d29cf64072e5c0478f39a480d8ef4.gif)
我將數(shù)據(jù)庫事務(wù)隔離性改為了read committted。
還是上面那張表:
如圖:窗口一
![](/d/20211018/d0a72f3bbdca12904e1542cc59528554.gif)
窗口二
![](/d/20211018/c5744a9532096d141e9f8c2bc64d6a0d.gif)
我在兩個窗口都開啟了事務(wù),當(dāng)窗口一進行數(shù)據(jù)操作后,并進行事務(wù)提交,在窗口二的事務(wù)開啟情況下,我去查詢,沒有查詢到剛才窗口一的數(shù)據(jù)操作記錄,這樣就避免了臟讀和不可重復(fù)讀。
有人說也避免了虛讀/幻讀,其實沒有。
看圖:
![](/d/20211018/2d192f38c1b80e9914d28c6f9d1d01f0.gif)
我在操作lisi賬戶時,數(shù)據(jù)只是發(fā)生修改的變化,但是當(dāng)我修改wangwu這個賬戶時,再去查詢出現(xiàn)了wangwu,賬戶的數(shù)據(jù),但是其實在我未操作前,wangwu賬戶的數(shù)據(jù)是查詢不出的。這就是幻讀/虛讀!
如果不理解幻讀/虛讀這塊,可以查一下InnoDB。
4.serializable
我就不演示了,開發(fā)不建議用,效率又慢,但是所有的問題都能避免??!
總結(jié)一下
事務(wù)隔離級別的性能:
read uncommitted>read committed>repeatable read>serialazable
事務(wù)隔離級別的安全性:
read uncommittedread committedrepeatable readserialazable
mysql 事務(wù)控制:
開啟事務(wù):start transaction;
提交:commit;
回滾:rollback;
您可能感興趣的文章:- mysql學(xué)習(xí)筆記之基礎(chǔ)知識
- MySQL中表子查詢與關(guān)聯(lián)子查詢的基礎(chǔ)學(xué)習(xí)教程
- MySQL中觸發(fā)器的基礎(chǔ)學(xué)習(xí)教程
- Mysql基礎(chǔ)入門 輕松學(xué)習(xí)Mysql命令
- 學(xué)習(xí)mysql之后的一點總結(jié)(基礎(chǔ))
- 快速學(xué)習(xí)MySQL基礎(chǔ)知識