最好的自助建站系統(tǒng)店鋪運(yùn)營(yíng)方案策劃
1 背景介紹
事務(wù)模板里拋異常,拋異常前的update操作成功,事務(wù)沒(méi)有回滾成功,業(yè)務(wù)數(shù)據(jù)還是落db了。debug代碼,發(fā)現(xiàn)GenericConnectionContext類(lèi)中derivedConnectionMap是空的,導(dǎo)致回滾代碼沒(méi)有執(zhí)行
2 解決方案
保證事務(wù)內(nèi)所有的 DAO 操作所涉及的數(shù)據(jù)源和事務(wù)模板所關(guān)聯(lián)的數(shù)據(jù)源都是同一個(gè)對(duì)象, bundle 都是 Spring 上下文隔離的,也需要 DAO 和事務(wù)模板在同一個(gè) bundle 內(nèi)。
需要注意創(chuàng)建事務(wù)模版地方的數(shù)據(jù)源,和 dao 對(duì)應(yīng)的數(shù)據(jù)源是同一個(gè),如果不是,需要重新建一個(gè)事務(wù)模版。
3 更多基礎(chǔ)知識(shí)
事務(wù)五個(gè)隔離
3.1** ISOLATION_DEFAULT:默認(rèn)隔離級(jí)別**
這是一個(gè)PlatfromTransactionManager默認(rèn)的隔離級(jí)別,使用數(shù)據(jù)庫(kù)默認(rèn)的事務(wù)隔離級(jí)別,
**oracle默認(rèn)的是.:READ_COMMITTED **,
**mysql默認(rèn)的是:REPEATABLE_READ **
另外四個(gè)與JDBC的隔離級(jí)別相對(duì)應(yīng);
3.2** **ISOLATION_READ_UNCOMMITTED:讀未提交
這是事務(wù)最低的隔離級(jí)別,它充許別外一個(gè)事務(wù)可以看到這個(gè)事務(wù)未提交的數(shù)據(jù)。
這種隔離級(jí)別會(huì)產(chǎn)生臟讀,不可重復(fù)讀和幻像讀。
3.3** ****ISOLATION_READ_COMMITTED:讀已提交 **
保證一個(gè)事務(wù)修改的數(shù)據(jù)提交后才能被另外一個(gè)事務(wù)讀取。另外一個(gè)事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)。
這種事務(wù)隔離級(jí)別可以避免臟讀出現(xiàn),但是可能會(huì)出現(xiàn)不可重復(fù)讀和幻像讀。
3.4** ****ISOLATION_REPEATABLE_READ:可重復(fù)讀 **
這種事務(wù)隔離級(jí)別可以防止臟讀,不可重復(fù)讀。但是可能出現(xiàn)幻像讀。
它除了保證一個(gè)事務(wù)不能讀取另一個(gè)事務(wù)未提交的數(shù)據(jù)外,還保證了避免下面的情況產(chǎn)生(不可重復(fù)讀)。
3.5** ****ISOLATION_SERIALIZABLE:序列化 **
這是花費(fèi)最高代價(jià)但是最可靠的事務(wù)隔離級(jí)別。事務(wù)被處理為順序執(zhí)行。
除了防止臟讀,不可重復(fù)讀外,還避免了幻像讀。
什么是 臟讀,不可重復(fù)讀,虛讀?
臟讀:指一個(gè)事務(wù)讀取了一個(gè)未提交事務(wù)的數(shù)據(jù)
**說(shuō)明:**事務(wù)1更新了記錄,但沒(méi)有提交,事務(wù)2讀取了更新后的行,然后事務(wù)T1回滾,現(xiàn)在T2讀取無(wú)效。
不可重復(fù)讀:在一個(gè)事務(wù)內(nèi)讀取表中的某一行數(shù)據(jù),多次讀取結(jié)果不同.一個(gè)事務(wù)讀取到了另一個(gè)事務(wù)提交后(update)的數(shù)據(jù).
**說(shuō)明:**事務(wù)1讀取記錄時(shí),事務(wù)2更新了記錄并提交,事務(wù)1再次讀取時(shí)可以看到事務(wù)2修改后的記錄;
虛讀(幻讀):在一個(gè)事務(wù)內(nèi)讀取了別的事務(wù)插入的數(shù)據(jù),導(dǎo)致前后讀取不一致(insert)
**說(shuō)明:**事務(wù)1讀取記錄時(shí)事務(wù)2增加了記錄并提交,事務(wù)1再次讀取時(shí)可以看到事務(wù)2新增的記錄;
不可重復(fù)讀與幻讀的區(qū)別?
不可重復(fù)讀的重點(diǎn)是修改: 同樣的條件, 你讀取過(guò)的數(shù)據(jù), 再次讀取出來(lái)發(fā)現(xiàn)值不一樣了
在一個(gè)事務(wù)中前后兩次讀取的結(jié)果并不一致,導(dǎo)致了不可重復(fù)讀。
例如:在事務(wù)1中,Mary 讀取了自己的工資為1000,操作并沒(méi)有完成
con1 = getConnection(); select salary from employee empId ="Mary";
在事務(wù)2中,這時(shí)財(cái)務(wù)人員修改了Mary的工資為2000,并提交了事務(wù).
con2 = getConnection(); update employee set salary = 2000; con2.commit();
在事務(wù)1中,Mary 再次讀取自己的工資時(shí),工資變?yōu)榱?000
//con1 select salary from employee empId ="Mary";
幻讀的重點(diǎn)在于新增或者刪除:
同樣的條件, 第1次和第2次讀出來(lái)的記錄數(shù)不一樣
例如:目前工資為1000的員工有10人。事務(wù)1,讀取所有工資為1000的員工。
con2 = getConnection(); Insert into employee(empId,salary) values("Lili",1000); con2.commit();
事務(wù)1再次讀取所有工資為1000的員工
select * from employee where salary =1000;
共讀取到了11條記錄,這就產(chǎn)生了幻讀。
從總的結(jié)果來(lái)看, 似乎不可重復(fù)讀和幻讀都表現(xiàn)為兩次讀取的結(jié)果不一致。
但如果你從控制的角度來(lái)看, 兩者的區(qū)別就比較大。 對(duì)于前者, 只需要鎖住滿足條件的記錄。 對(duì)于后者, 要鎖住滿足條件及其相近的記錄。
4 事務(wù)的四個(gè)特性?
事務(wù)的四個(gè)特性(ACID)
4.1 原子性
原子性(Atomicity):操作這些指令時(shí),要么全部執(zhí)行成功,要么全部不執(zhí)行。只要其中一個(gè)指令執(zhí)行失敗,所有的指令都執(zhí)行失敗,數(shù)據(jù)進(jìn)行回滾,回到執(zhí)行指令之前的數(shù)據(jù)狀態(tài)
4.2 一致性
一致性(Consistency):事務(wù)的執(zhí)行使數(shù)據(jù)從一個(gè)狀態(tài)轉(zhuǎn)換為另一個(gè)狀態(tài),但是對(duì)于整個(gè)數(shù)據(jù)的完整性保持穩(wěn)定
4.3 隔離性
隔離性(Isolation):是當(dāng)多個(gè)用戶并發(fā)訪問(wèn)數(shù)據(jù)庫(kù)時(shí),比如操作同一張表時(shí),數(shù)據(jù)庫(kù)為每一個(gè)用戶開(kāi)啟的事務(wù),不能被其他事務(wù)的操作所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離。
即:要達(dá)到這么一種效果:對(duì)于任意兩個(gè)并發(fā)的事務(wù)T1和T2,在事務(wù)T1看來(lái),T2要么在T1開(kāi)始之前就已經(jīng)結(jié)束,要么在T1結(jié)束之后才開(kāi)始,這樣每個(gè)事務(wù)都感覺(jué)不到有其他事務(wù)在并發(fā)地執(zhí)行
4.4 持久性
持久性(Durability):當(dāng)事務(wù)正確完成后,它對(duì)于數(shù)據(jù)的改變時(shí)永久性的