所謂事務,就是針對資料庫的一組操作(多條sql)
位於同乙個事務的操作具備同步的特點,也就是要麼都成功,要麼都失敗
在實際中,我們的很多操作都是需要由多條sql來共同完成的,例如,a賬戶給b賬戶轉賬就會對應兩條sql
update account set money=money-100 where name=『a』;
update account set money=money+100 where name=『b』;
假設第一條sql成功了,而第二條sql失敗了,這樣就會導致a賬戶損失了100元,而b賬戶並未得到100元
如果將兩條sql放在乙個sql中,當第二條語句失敗時,第一條sql語句也同樣不會生效,
這樣a賬戶就不會有任何的損失
預設情況下,我們向資料庫傳送的sql語句是會被自動提交的,開啟事務就是相當於關閉自動提交功能,改為手動提交,我們只需要將提交事務的操作放在最後乙個操作,這樣一來,如果在提交事務之前出現異常,由於沒有執行提交操作,事務中未提交的操作就會被回滾掉
account
.sql
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
aaa 給 bbb 轉賬 100元
update account set money=money-100 where name=
'aaa';
// 異常退出
update account set money=money+100 where name=
'bbb';
// 查詢結果
select * from accont;
如果開啟事務就可以避免剛才的錯誤發生
// 開啟事務
start transaction;
// 如果操作執行完畢,我們需要將事務提交
commit;
// 還可以手動回顧事務中所有未提交的事務
rollback;
命令列做實驗得出結論:
如果開了乙個事務, 又敲了一次 start transaction 再次開啟事務, 前乙個事務會自動提交
在使用 jdbc 運算元據庫時,需要使用 connection 物件對事務進行管理
// 開啟事務
connection.setautocommit(false);
//設定自動提交為false
// 回滾事務
connection.rollback();
//提交事務
connection.commit();
在 jdbc 程式中我們還可以設定回滾點, 讓事務回顧到指定的回滾點,而不是自動回滾所有未提交的操作
需要將程式中的異常捕獲,在catch語句塊中回滾事務,在finally中提交事務
注意 , 將 commit 操作放在 finally 中是為了保證提交未回滾的事務操作
事務有四大特性,一般來講,判斷乙個資料庫是否支援事務,就看資料庫是否支援這四個特性
l 原子性(atomicity)
原子性是指事務是乙個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。
l 一致性(consistency)
事務必須使資料庫從乙個一致性狀態變換到另外乙個一致性狀態。
l 隔離性(isolation)
事務的隔離性是多個使用者併發訪問資料庫時,資料庫為每乙個使用者開啟的事務,不能被其他事務的運算元據所干擾,多個併發事務之間要相互隔離。
l 永續性(durability)
永續性是指乙個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響。
由於資料庫是多執行緒併發訪問的,所以很容易出現多個執行緒同時開啟事務的情況
多執行緒開事務容易引起 贓讀、不可重複讀、幻讀 的情況發生
贓讀:dirty read
是指乙個事務讀取了另乙個事務未提交的資料,這是相當危險的。
設想一下,a要給b轉賬100元購買商品, 如果a開啟了乙個事務做了轉賬的工作
update account set money=money+100 while name=『b』;
update account set money=money -100 while name=『a
』;
a先不提交事務,通知b來查詢
這時b來查詢賬戶,由於會讀到a開啟的事務中未提交的資料,就會發現a確實給自己轉了100元,
自然就會給a發貨,a等b發貨後就將事務回滾,不提交,此時,b就會受到損失
不可重複讀:non-repeatable read
是指事務中兩次查詢的結果不一致,原因是在查詢的過程中其他事務做了更新的操作 update
例如,銀行做報表,第一次查詢a賬戶有100元,第二次查詢a賬戶有200元,原因是期間a存了100元
這樣就會導致一行多次統計的報表不一致
和髒讀的區別是:
髒讀是讀取前一事務未提交的髒資料,不可重複讀是在事務內重複讀取了別的執行緒已提交的資料。
有的時候大家會認為這樣的結果是正確的,沒問題
我們可以考慮這樣一種情況,比如銀行程式需要將查詢結果分別輸出到電腦螢幕和寫到檔案中,結果在乙個事務中針對輸出的目的地,進行的兩次查詢不一致,導致檔案和螢幕中的結果不一致,銀行工作人員就不知道以哪個為準了。
幻讀:phantom read 又名虛讀
是指在乙個事務內兩次查詢中資料筆數不一致
幻讀和不可重複讀有些類似,是指兩次查詢過程中,其他事務做了插入記錄的操作,導致記錄數有所增加
insert
例如銀行做報表統計account表中所有使用者的總額時,此時總共
五個賬戶,總金額為500元,這時有乙個新的賬戶產生了,並且
存了100元,這時銀行再統計會發現帳戶總金額為600元了,造
成虛讀同樣會使銀行遇到同樣的困惑
實驗發現不會出現虛讀
來自網路的解釋:
幻讀只是在理論上會發生的一種情況,而現實操作中並不是一定會發生
為了避免多執行緒開事務引發的問題,我們需要將事務進行隔離
事務有四種隔離級別,不同的隔離級別可以防止不同的錯誤發生
serializable:可序列化,能避免髒讀、不可重複讀、幻讀情況的發生
repeatable read:可重讀,能避免髒讀、不可重複讀情況的發生
read committed:讀取提交的內容,可避免髒讀情況發生
read uncommitted:讀取未提交的內容最低級別,避免不了任何情況
操作:設定事務隔離級別
set transaction isolation level
查詢當前事務隔離級別
select @@tx_isolation
查詢看到的都是快照
位於事務中的多次查詢,如果隔離級別設定為
repeatable read,
那麼多次查詢讀的就是乙個快照
說白了就是不更新快照
JDBC中的事務
步驟 開啟新事務 編寫組成事務的一組sql語句 結束事務 細節 要求開啟事務的連線物件和獲取命令的連線物件必須是同乙個,否則事務無效 有點執行緒同步的感覺 例項 兩個轉賬之間的轉賬 jdbcutils為封裝連線及釋放操作的工具類 public class testtransaction 使用事務 t...
JDBC中事務的使用
當jdbc程式向資料庫獲得乙個connection物件時,預設情況下這個connection物件會自動向資料庫提交在它上面傳送的sql語句。若想關閉這種預設提交方式,讓多條sql在乙個事務中執行,並且保證這些語句是在同一時間共同執行的時,我們就應該為這多條語句定義乙個事務。其中,銀行轉賬這一事例,最...
JDBC中事務的使用
當jdbc程式向資料庫獲得乙個connection物件時,預設情況下這個connection物件會自動向資料庫提交在它上面傳送的sql語句。若想關閉這種預設提交方式,讓多條sql在乙個事務中執行,並且保證這些語句是在同一時間共同執行的時,我們就應該為這多條語句定義乙個事務。其中,銀行轉賬這一事例,最...