一、事務(wù)的概念
事務(wù)指邏輯上的一組操作,組成這組操作的各個(gè)單元,要不全部成功,要不全部不成功。
例如:A——B轉(zhuǎn)帳,對(duì)應(yīng)于如下兩條sql語句
update from account set money=money+100 where name=‘b’;
update from account set money=money-100 where name=‘a(chǎn)’;
二、事務(wù)的使用
- JDBC開啟事務(wù)的命令
start transaction 開啟事務(wù)
Rollback 回滾事務(wù)
Commit 提交事務(wù) - 當(dāng)Jdbc程序向數(shù)據(jù)庫(kù)獲得一個(gè)Connection對(duì)象時(shí),默認(rèn)情況下這個(gè)Connection對(duì)象會(huì)自動(dòng)向數(shù)據(jù)庫(kù)提交在它上面發(fā)送的SQL語句。若想關(guān)閉這種默認(rèn)提交方式,讓多條SQL在一個(gè)事務(wù)中執(zhí)行,可使用下列語句:
- JDBC控制事務(wù)語句
Connection.setAutoCommit(false);
Connection.rollback();
Connection.commit();
三、事務(wù)的特性
- 原子性(Atomicity)?原子性是指事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
- 一致性(Consistency)?事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)變換到另外一個(gè)一致性狀態(tài)。
- 隔離性(Isolation)?事務(wù)的隔離性是多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫(kù)時(shí),數(shù)據(jù)庫(kù)為每一個(gè)用戶開啟的事務(wù),不能被其他事務(wù)的操作數(shù)據(jù)所干擾,多個(gè)并發(fā)事務(wù)之間要相互隔離。
- 持久性(Durability)?持久性是指一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就是永久性的,接下來即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響。
以談戀愛為例子理解:
A:原子性,即要么泡妞成功,要么泡妞不成功,絕對(duì)不能出現(xiàn)曖昧不清的情況
C:一致性,即如果對(duì)方對(duì)你好,你就不能耍脾氣,也要對(duì)對(duì)方好,狀態(tài)要保持一致
I:隔離性,談戀愛期間錢歸錢,愛歸愛,兩者不能混淆,愛不應(yīng)收到窮富的干擾
D:持久性,這個(gè)你懂的。。。。。。。別誤解了,我指的是戀愛這個(gè)應(yīng)該是一輩子的,是永久性的
出自http://www.zhihu.com/question/30272728
四、事務(wù)的隔離級(jí)別
- 多個(gè)線程開啟各自事務(wù)操作數(shù)據(jù)庫(kù)中數(shù)據(jù)時(shí),數(shù)據(jù)庫(kù)系統(tǒng)要負(fù)責(zé)隔離操作,以保證各個(gè)線程在獲取數(shù)據(jù)時(shí)的準(zhǔn)確性。如果不考慮隔離性,可能會(huì)引發(fā)如下問題:
a. 臟讀:指一個(gè)事務(wù)讀取了另外一個(gè)事務(wù)未提交的數(shù)據(jù)
假設(shè)A向B轉(zhuǎn)帳100元,對(duì)應(yīng)sql語句如下所示
1.update account set money=money+100 while name=‘b’;
2.update account set money=money-100 while name=‘a(chǎn)’;
當(dāng)?shù)?條sql執(zhí)行完,第2條還沒執(zhí)行(A未提交時(shí)),如果此時(shí)B查詢自己的帳戶,就會(huì)發(fā)現(xiàn)自己多了100元錢。如果A等B走后再回滾,B就會(huì)損失100元。
b. 不可重復(fù)讀:在一個(gè)事物內(nèi)讀取表中的某一行數(shù)據(jù),多次讀取結(jié)果不同。
例如銀行想查詢A帳戶余額,第一次查詢A帳戶為200元,此時(shí)A向帳戶內(nèi)存了100元并提交了,銀行接著又進(jìn)行了一次查詢,此時(shí)A帳戶為300元了。銀行兩次查詢不一致,可能就會(huì)很困惑,不知道哪次查詢是準(zhǔn)的。
和臟讀的區(qū)別是,臟讀是讀取前一事務(wù)未提交的臟數(shù)據(jù),不可重復(fù)讀是重新讀取了前一事務(wù)已提交的數(shù)據(jù)。
很多人認(rèn)為這種情況就對(duì)了,無須困惑,當(dāng)然是后面的為準(zhǔn)。我們可以考慮這樣一種情況,比如銀行程序需要將查詢結(jié)果分別輸出到電腦屏幕和寫到文件中,結(jié)果在一個(gè)事務(wù)中針對(duì)輸出的目的地,進(jìn)行的兩次查詢不一致,導(dǎo)致文件和屏幕中的結(jié)果不一致,銀行工作人員就不知道以哪個(gè)為準(zhǔn)了。
c. 虛讀:是指在一個(gè)事務(wù)內(nèi)讀取到了別的事務(wù)插入的數(shù)據(jù),導(dǎo)致前后讀取不一致
如丙存款100元未提交,這時(shí)銀行做報(bào)表統(tǒng)計(jì)account表中所有用戶的總額為500元,然后丙提交了,這時(shí)銀行再統(tǒng)計(jì)發(fā)現(xiàn)帳戶為600元了,造成虛讀同樣會(huì)使銀行不知所措,到底以哪個(gè)為準(zhǔn)。
2. 數(shù)據(jù)庫(kù)四種隔離級(jí)別:
a. Serializable:可避免臟讀、不可重復(fù)讀、虛讀情況的發(fā)生。(串行化)它會(huì)鎖表,可以解決所有問題.
b. Repeatable read:可避免臟讀、不可重復(fù)讀情況的發(fā)生。(可重復(fù)讀)可以解決臟讀,可以解決不可重復(fù)讀,不能解決虛讀.
c. Read committed:可避免臟讀情況發(fā)生。(讀已提交)可以解決臟讀,其它解決不了
d. Read uncommitted:最低級(jí)別,以上情況均無法保證。(讀未提交)什么問題也解決不了
安全性:serializable > repeatable read > read committed > read uncommitted
性能 :serializable < repeatable read < read committed < read uncommitted
結(jié)論: 實(shí)際開發(fā)中,通常不會(huì)選擇 serializable 和 read uncommitted ,mysql默認(rèn)隔離級(jí)別 repeatable read ,oracle默認(rèn)隔離級(jí)別 read committed
3. 設(shè)置隔離級(jí)別
a. mysql中設(shè)置
i. 查看事務(wù)隔離級(jí)別
select @@tx_isolation 查詢當(dāng)前事務(wù)隔離級(jí)別
mysql中默認(rèn)的事務(wù)隔離級(jí)別是 Repeatable read.
ii. 擴(kuò)展:oracle 中默認(rèn)的事務(wù)隔離級(jí)別是 Read committed
iii. mysql中怎樣設(shè)置事務(wù)隔離級(jí)別
set session transaction isolation level 設(shè)置事務(wù)隔離級(jí)別
b. jdbc中設(shè)置
i. 在jdbc中設(shè)置事務(wù)隔離級(jí)別
使用java.sql.Connection接口中提供的方法
void setTransactionIsolation(int level) throws SQLException
ii. 參數(shù)level可以取以下值:
level - 以下 Connection 常量之一:
Connection.TRANSACTION_READ_UNCOMMITTED、
Connection.TRANSACTION_READ_COMMITTED、
Connection.TRANSACTION_REPEATABLE_READ
Connection.TRANSACTION_SERIALIZABLE。
iii. 注意,不能使用 Connection.TRANSACTION_NONE,因?yàn)樗付瞬皇苤С值氖聞?wù)。