jdbc中的事務

2021-09-01 11:11:59 字數 3766 閱讀 1698

所謂事務,就是針對資料庫的一組操作(多條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在乙個事務中執行,並且保證這些語句是在同一時間共同執行的時,我們就應該為這多條語句定義乙個事務。其中,銀行轉賬這一事例,最...