事務(wù)
1.事務(wù)的概念:
事務(wù)是指邏輯上的一組操作,這組操作要么同時(shí)完成要么同時(shí)不完成碎捺。參考轉(zhuǎn)賬操作彤枢。
2.
如果你自己不去控制事務(wù),數(shù)據(jù)庫默認(rèn)一條sql語句就處在自己單獨(dú)的事務(wù)當(dāng)中固翰。
3.也可以使用命令去開啟一個(gè)事務(wù):
start transaction;--開啟事務(wù)狼纬,這條語句之后的sql語句將處在一個(gè)事務(wù)當(dāng)中,這些sql語句并不會(huì)立即執(zhí)行
Commit--提交事務(wù)骂际,一旦提交事務(wù)疗琉,事務(wù)中的所有sql語句才會(huì)執(zhí)行。
Rollback -- 回滾事務(wù)歉铝,將之前所有的sql取消盈简。
conn.setAutoCommit(false);
conn.commit();
conn.rollback();
conn.setSavePoint();
conn.rollback(sp);
4.事務(wù)的四大特性ACID
(1)原子性:事務(wù)的一組操作是原子的不可再分割的,這組操作要么同時(shí)完成要么同時(shí)不完成。
(2)一致性: 事務(wù)在執(zhí)行前后數(shù)據(jù)的完整性保持不變柠贤。數(shù)據(jù)庫在某個(gè)狀態(tài)下符合所有的完整性約束的狀態(tài)叫做數(shù)據(jù)庫具有完整性香浩。在解散一個(gè)部門時(shí)應(yīng)該同時(shí)處理員工表中的員工保證這個(gè)事務(wù)結(jié)束后,仍然保證所有的員工能找到對應(yīng)的部門臼勉,滿足外鍵約束邻吭。
(3)隔離性:當(dāng)多個(gè)事務(wù)同時(shí)操作一個(gè)數(shù)據(jù)庫時(shí),可能存在并發(fā)問題宴霸,此時(shí)應(yīng)保證各個(gè)事務(wù)要進(jìn)行隔離囱晴,事務(wù)之間不能互相干擾。
(4)持久性:持久性是指一個(gè)事務(wù)一旦被提交猖败,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的速缆,不能再回滾。
5.事務(wù)的隔離性導(dǎo)致的問題(所有的問題都是在某些情況下才會(huì)導(dǎo)致問題)
~臟讀:一個(gè)事務(wù)讀取到了另一個(gè)事務(wù)未提交的數(shù)據(jù)恩闻。
1 | a? ? |? 1000
2 | b? ? |? 1000
b--->a
start transaction;
update account set money=money-100 where name='b';
update account set money=money+100 where name='a';
rollback;
select * from account where name = 'a';1000 1000
~不可重復(fù)讀:在一個(gè)事務(wù)內(nèi)讀取表中的某一行數(shù)據(jù)艺糜,多次讀取結(jié)果不同.
start transaction:
活期存款:1000
定期存款:1000
固定資產(chǎn): 2000
--------------
開啟事務(wù)
取走獲取存款1000
提交事務(wù)
--------------
總資產(chǎn):3000
~幻讀(虛讀):一個(gè)事務(wù)讀取到了另一個(gè)事務(wù)插入的數(shù)據(jù)(已提交)
a 2000
b 2000
c 2000
start transaction;
select sum(money) from account;6000
--------------
開啟事務(wù)
創(chuàng)建一個(gè)賬戶并存入1000塊錢
提交了事務(wù)
--------------
select count(*)from account;4
avgMoney = allMoney/count;6000/4=1500
6.數(shù)據(jù)庫的隔離級別
~Read uncommitted:如果將數(shù)據(jù)庫設(shè)定為此隔離級別幢尚,數(shù)據(jù)庫將會(huì)有臟讀破停、不可重復(fù)度、幻讀的問題尉剩。
~Read committed:如果將數(shù)據(jù)庫設(shè)定為此隔離級別真慢,數(shù)據(jù)庫可以防止臟讀,但有不可重復(fù)度理茎、幻讀的問題黑界。
~Repeatable read: 如果將數(shù)據(jù)庫設(shè)定為此隔離級別,數(shù)據(jù)庫可以防止臟讀皂林、不可重復(fù)度朗鸠,但是不能防止幻讀。
~Serializable:將數(shù)據(jù)庫串行化,可以避免臟讀础倍、不可重復(fù)讀烛占、幻讀。
安全性來說:Serializable>Repeatable read>Read committed>Read uncommitted
效率來說:Serializable<Repeatable read<Read committed
通常來說沟启,一般的應(yīng)用都會(huì)選擇Repeatable read或Read committed作為數(shù)據(jù)庫隔離級別來使用忆家。
mysql默認(rèn)的數(shù)據(jù)庫隔離級別為:REPEATABLE-READ
如何查詢當(dāng)前數(shù)據(jù)庫的隔離級別?select @@tx_isolation;
如何設(shè)置當(dāng)前數(shù)據(jù)庫的隔離級別德迹?set [global/session] transaction isolation level ...;
~此種方式設(shè)置的隔離級別只對當(dāng)前連接起作用芽卿。
set transaction isolation level read uncommitted;
set session transaction isolation level read uncommitted;
~此種方式設(shè)置的隔離級別是設(shè)置數(shù)據(jù)庫默認(rèn)的隔離級別
set global transaction isolation level read uncommitted;
7.鎖機(jī)制:
共享鎖:共享鎖和共享鎖可以共存。
排他鎖:排他鎖和所有鎖都不能共存浦辨。
在非串行化下蹬竖,所有的查詢都不加鎖沼沈,所有的修改操作都會(huì)加排他鎖。
在串行化下币厕,所有的查詢都加共享鎖列另,所有的修改都加排他鎖。
死鎖
8.更新丟失
如果多個(gè)線程操作旦装,基于同一個(gè)查詢結(jié)構(gòu)對表中的記錄進(jìn)行修改页衙,那么后修改的記錄將會(huì)覆蓋前面修改的記錄,前面的修改就丟失掉了阴绢,這就叫做更新丟失店乐。
Serializable可以防止更新丟失問題的發(fā)生。其他的三個(gè)隔離級別都有可能發(fā)生更新丟失問題呻袭。
Serializable雖然可以防止更新丟失眨八,但是效率太低,通常數(shù)據(jù)庫不會(huì)用這個(gè)隔離級別左电,所以我們需要其他的機(jī)制來防止更新丟失:
樂觀鎖和悲觀鎖不是數(shù)據(jù)庫中真正存在的鎖廉侧,只是人們在解決更新丟失時(shí)的不同的解決方案,體現(xiàn)的是人們看待事務(wù)的態(tài)度篓足。
悲觀鎖:
隔離級別不設(shè)置為Serializable段誊,防止效率過低。
在查詢時(shí)手動(dòng)加上排他鎖栈拖。
如果數(shù)據(jù)庫中的數(shù)據(jù)查詢比較多而更新比較少的話连舍,悲觀鎖將會(huì)導(dǎo)致效率低下。
樂觀鎖:
在表中增加一個(gè)version字段涩哟,在更新數(shù)據(jù)庫記錄是將version加一索赏,從而在修改數(shù)據(jù)時(shí)通過檢查版本號是否改變判斷出當(dāng)前更新基于的查詢是否已經(jīng)是過時(shí)的版本。
如果數(shù)據(jù)庫中數(shù)據(jù)的修改比較多贴彼,更新失敗的次數(shù)會(huì)比較多参滴,程序需要多次重復(fù)執(zhí)行更新操作。