聲明:本欄目所使用的素材都是凱哥學堂VIP學員所寫,學員有權匿名,對文章有最終解釋權;凱哥學堂旨在促進VIP學員互相學習的基礎上公開筆記。
事務與鎖是關聯在一起的,事務->鎖
早期數據庫是單機版居多,不存在訪問量很大和多人同時訪問的情況,因此數據安全性比較高。在現在的網絡型數據庫大行的時代,往往會出現同時訪問的情況,這種會對數據安全性產生隱患。
寫業(yè)務代碼操作數據庫中數據的時候,不僅僅是一條兩條SQL語句的,很多條SQL語句需要按順序來訪問數據庫: 比如寫一個購買商品的業(yè)務:
1.添加一條數據進入訂單表
2.減少商品庫存
3.增加一條購買數據
4.增加一條物流需求
5.寫日志數據庫
或者是學生退學業(yè)務:
1.將學生表的學生信息狀態(tài)改為退學
2.將學生卡狀態(tài)改為暫停
3.增加一條學生的金額退還記 錄 4.刪除學生日常信息
5.添加學生退學記錄
可見業(yè)務代碼中需要執(zhí)行的SQL語句是很多的,這么多SQL語句的執(zhí)行只是為了完成一個業(yè)務。
這么多SQL語句,如果其中的一條SQL語句執(zhí)行失敗了,則這整個業(yè)務就是失敗的了。
比如,如果第三條SQL執(zhí)行失敗了,但是第一、二條SQL語句還是執(zhí)行成功了的,而第四、五條記錄則執(zhí)行失敗,這樣子的話,數據庫中的數據就不是完整的了。 也就是說,我們的業(yè)務代碼的SQL語句寫出來,不一定是它們就能順利執(zhí)行、不一定就能保證它們能夠符合業(yè)務邏輯需求,在沒有接觸到事務之前,這些是無法保證的。
那么事務就是用來保證如上面的那5條SQL語句能夠順利執(zhí)行,能夠按照你的邏輯全部正常通過。
我們寫業(yè)務代碼的時候,涉及到很多條SQL語句,如果我們寫了20條SQL語句,但是第10條SQL語句執(zhí)行不通過或者不符合業(yè)務邏輯需求,我們需要回到最開始再去從頭開始執(zhí)行SQL語句,前面執(zhí)行了的十條SQL語句作廢,這種回到最開頭的情況叫做回滾。如果你不回滾,接著把不通過SQL語句后面的語句繼續(xù)執(zhí)行的話,就會發(fā)生數據不一致的情況了。數據不完整、不同步了。會導致系統(tǒng)數據不健全。
事務就是用來確保所有SQL語句順利執(zhí)行,這里的順利執(zhí)行,并不僅僅是指不會報錯,而是這個SQL語句是按照你的業(yè)務邏輯來執(zhí)行,就算一條SQL語句不報錯,但是沒有按照業(yè)務邏輯的話,也可以讓它前面的所有SQL語句作廢,進行回滾。當所有的SQL語句全部按照你的業(yè)務邏輯意思順利執(zhí)行后,就可以把它寫入到數據庫中去永久執(zhí)行。
事務不可分割,不可以一分為二來執(zhí)行。
事務:
1.提交:如果你覺得所有的SQL語句執(zhí)行都是正確的,你可以調用提交,永久的寫入到數據庫、永久保存
2.回滾:在執(zhí)行SQL語句過程中,發(fā)生任何問題,都可以回滾、取消前面執(zhí)行的所有SQL語句,回到初始狀態(tài)。
今后業(yè)務涉及到的很多的SQL語句,在把所有的SQL語句發(fā)送到數據庫中去操作數據之前,先建立一個事務,在事務里面一條一條的執(zhí)行所有需要的SQL語句,執(zhí)行完了之后,你在決定到底是提交還是回滾。提交,則所有的SQL語句會全部寫入數據庫中保存、執(zhí)行?;貪L,則會前面所有執(zhí)行的SQL語句全部取消,事務保證整個業(yè)務的完整執(zhí)行、確保了數據的一致性。
跨行取錢:本行取錢的時候是本行系統(tǒng),在最開始登陸的時候會調用本系統(tǒng)的驗證模塊來驗證賬戶密碼,但是跨行取錢的時候,不是使用的本行系統(tǒng),所以最開始登陸的時候不調用別行的系統(tǒng)來驗證,而是等你登陸進去后,選好了取款、查詢等操作后,再一起把需要進行的驗證、操作內容等SQL發(fā)送到別行系統(tǒng)上去執(zhí)行。所以跨行取錢的時候,你輸入任何密碼都會登陸進去。
取錢時涉及的事務:當你取200元的時候,用戶同意取錢,會在數據庫中減去200+2元,然后準備給你出鈔票,如果此時ATM突然掉電而沒有拿出錢,這里系統(tǒng)會回滾,會讓數據庫中數據回到未扣款時的狀態(tài),也就是會把200+2給你加回去。這樣能保證這個業(yè)務的完整執(zhí)行和數據的安全性、完整性。
事務不是屬于JDBC的技術,是數據庫本身的一種機制、特性,但是JDBC可以控制事務,可以控制事務的開始、回滾、提交等。事務的結束有兩種要么回滾要么提交。
JDBC中事務有兩種模式1.自動事務(默認)2.手動事務(自己一定要提交或者回滾來結束事務)。
自動事務:只要你的SQL語句正確執(zhí)行就會提交,不管你的SQL語句的執(zhí)行結果是否是業(yè)務邏輯所需要的,都會提交。
學了事務之后,就一定使用事務。

JDBC中的事務在Connection接口下管理,設置事務模式的方法是setAutoCommit(),參數可以是true或者false,true的話表示自動提交式事務管理,false表示手動提交式事務管理。默認是true。

在手動式提交事務管理中有兩個方法,commit和rollback,這兩個方法是用來提交和回滾的。手動情況下,要自己親自調用這兩個方法。

當選擇手動提交事務模式的時候,如果最后的時候沒有提交或者回滾,會默認回滾。


這里使用Statement來執(zhí)行SQL語句,設置為手動提交模式,但是最后沒有提交也沒有回滾,此時會自動回滾,所以數據庫中數據還在。

當你調用的一個事務結束之后(rollback或者commit),新的事務又可以開始使用了。


這里一個連接中有兩條SQL語句,有一個事務,兩條SQL語句st和pst,等兩個SQL語句執(zhí)行完后,一起提交。


而上面這種情況是有兩個事務,第一個事務st執(zhí)行完后,手動提交了,然后數據庫中的數據刪除了,然后執(zhí)行第二個事務,第二個事務沒有提交也沒有回滾,則默認回滾,所以顯示數組里都是1,表示插入執(zhí)行了,但是因為最后又回滾了,回滾到了事務最開始時,數據庫中沒有數據的狀態(tài),所以數據庫中仍然沒有數據。


把模式改為自動提交模式,最后一個事務里的兩條SQL語句都會默認提交。


這種情況,最開始把事務設置為自動模式,第一個SQL語句執(zhí)行,把數據庫中的所有數據刪除了,然后等待執(zhí)行第二個SQL語句,并且在執(zhí)行第二個SQL語句前把模式改為手動了。執(zhí)行完第二條SQL語句后,往數據庫中插入了10條數據,這樣兩條SQL語句算是執(zhí)行完了,然后在決定這兩條SQL語句是提交還是回滾了,因為執(zhí)行完第二條SQL語句后,模式是手動的了,因為沒有寫明是提交還是回滾,就默認回滾了,就會回滾到第二條SQL語句沒有執(zhí)行前的哪種狀態(tài),也就是數據沒有的狀態(tài)。

需注意,如果你把模式設置為自動模式的話,就不能在手動的去調用conn.rollback或者conn.commit了,不然會報錯。


這種情況下,有兩個事務,第一個事務是手動模式,st執(zhí)行完SQL語句后,手動提交了,所以數據刪除了,第二個事務是自動模式,pst執(zhí)行完后,會自動提交,所以又添加進來10行數據,最后結果還是10行數據。



這種情況最開始是5條數據,往里面插入數據,開始設置事務為自動模式,執(zhí)行第一條SQL語句,插入一條數據,然后在執(zhí)行第二條SQL語句前把事務模式改為手動模式,再插入另外一條SQL語句,兩條SQL語句完成了之后,一起決定這兩條SQL語句是提交還是回滾的時候,手動模式,因為沒有顯示聲明,所以默認回滾了,回滾到第二條SQL語句開始執(zhí)行前的狀態(tài),所以數據庫中只會【學Java,到凱哥學堂kaige123.com】插入第一條數據,但是實際上第二條數據也插入過的,不過回滾的時候又把它刪除了,看uid從348->350,可以知道中間空了一個349,就是第二條插入后又被刪除了的那個。


