今天是學(xué)習(xí)計(jì)劃的第三天,今天打算繼續(xù)昨天探討的事務(wù)問題。
所以监右,今天的學(xué)習(xí)內(nèi)容是事務(wù)特性及隔離問題慨畸。
那事務(wù)都具有哪些特性呢?
- 原子性:原子性是指事務(wù)是一個(gè)不可分割的工作單位谢翎,事務(wù)中的操作要么都發(fā)生,要么都不發(fā)生。
- 一致性:事務(wù)前后數(shù)據(jù)的完整性必須保持一致遍愿。
- 隔離性:事務(wù)的隔離性是指多個(gè)用戶并發(fā)訪問數(shù)據(jù)庫(kù)時(shí),一個(gè)用戶的事務(wù)不能被其它用戶的事務(wù)所干擾耘斩,多個(gè)并發(fā)事務(wù)之間數(shù)據(jù)要相互隔離沼填。
- 持久性:持久性是指一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變就是永久性的括授,接下來即使數(shù)據(jù)庫(kù)發(fā)生故障也不應(yīng)該對(duì)其有任何影響坞笙。
多個(gè)線程開啟各自事務(wù)操作數(shù)據(jù)庫(kù)中的數(shù)據(jù)時(shí),數(shù)據(jù)庫(kù)系統(tǒng)要負(fù)責(zé)隔離操作荚虚,以保證各個(gè)線程在獲取數(shù)據(jù)時(shí)的準(zhǔn)確性薛夜。如果不考慮隔離,可能會(huì)引發(fā)如下問題版述。
- 臟讀
指一個(gè)事務(wù)讀取了另外一個(gè)事務(wù)未提交的數(shù)據(jù)梯澜。
這是非常危險(xiǎn)的。舉個(gè)例子:假設(shè)A向B轉(zhuǎn)賬100元渴析,對(duì)應(yīng)的sql語句如下
update account set money = money - 100 where name = 'a';
update account set money = money + 100 where name = 'b';
當(dāng)?shù)谝粭lsql語句執(zhí)行完晚伙,第二條還沒執(zhí)行(A未提交時(shí)),如果此時(shí)B查詢自己的賬戶俭茧,就會(huì)發(fā)現(xiàn)自己多了100元錢咆疗,如果A等B走后再回滾,B就會(huì)以為轉(zhuǎn)賬成功了母债,但是錢又返還給了A午磁,從而導(dǎo)致B損失100元
臟讀被認(rèn)為是數(shù)據(jù)庫(kù)中的最重要問題,是不被任何數(shù)據(jù)庫(kù)所允許的。
- 不可重復(fù)讀
在一個(gè)事務(wù)內(nèi)讀取表中的某一行數(shù)據(jù)漓踢,多次讀取結(jié)果不同牵署。
舉個(gè)例子:例如銀行想查詢A帳戶余額,第一次查詢A帳戶為200元喧半,此時(shí)A向帳戶存了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)了绷雏。
不可重復(fù)讀在有些數(shù)據(jù)庫(kù)被認(rèn)為是沒有問題的头滔,所以它在某些數(shù)據(jù)庫(kù)中允許出現(xiàn)。 - 虛度(幻讀)
是指在一個(gè)事務(wù)內(nèi)讀取到了別的事務(wù)插入的數(shù)據(jù)涎显,導(dǎo)致前后讀取不一致坤检。
舉個(gè)例子:假如丙存款100元未提交,這時(shí)銀行做報(bào)表統(tǒng)計(jì)account表中所有用戶的總額為500元期吓,然后丙提交了早歇,這時(shí)銀行再統(tǒng)計(jì)發(fā)現(xiàn)帳戶為600元了,造成虛讀同樣會(huì)使銀行不知所措膘婶,到底以哪個(gè)為準(zhǔn)。
會(huì)發(fā)現(xiàn)蛀醉,虛讀和不可重復(fù)讀是十分相似的悬襟,以致于很多人很難分辨它們,你只需要知道拯刁,它們最大的區(qū)別是:不可重復(fù)讀讀取到的是更新(update)數(shù)據(jù)脊岳,而虛讀讀取到的是插入(insert)數(shù)據(jù)。
同樣,虛讀在有些數(shù)據(jù)庫(kù)也被認(rèn)為不是問題割捅,允許該現(xiàn)象出現(xiàn)奶躯。
說完了引發(fā)的問題后,我們引出今天的主角亿驾,事務(wù)隔離級(jí)別嘹黔。
數(shù)據(jù)庫(kù)共定義了四種隔離級(jí)別:
- Serializable:可避免臟讀、不可重復(fù)讀莫瞬、虛讀情況的發(fā)生儡蔓。(串行化)
- Repeatable read:可避免臟讀、不可重復(fù)讀情況的發(fā)生疼邀。(可重復(fù)讀)不可以避免虛讀
- Read committed:可避免臟讀情況發(fā)生(讀已提交)
- Read uncommitted:最低級(jí)別喂江,以上情況均無法保證。(讀未提交)
隔離級(jí)別由高到低排列:Serializable>Repeatable read>Read committed>Read uncommitted
數(shù)據(jù)庫(kù)隔離問題危害級(jí)別由高到低:臟讀>不可重復(fù)讀>虛讀
在Oracle數(shù)據(jù)庫(kù)中旁振,默認(rèn)隔離級(jí)別是Read committed
在MySQL數(shù)據(jù)庫(kù)中获询,默認(rèn)隔離級(jí)別是Repeatable read
由此可以發(fā)現(xiàn),基本所有的數(shù)據(jù)庫(kù)都不會(huì)把隔離級(jí)別設(shè)置成最高拐袜,也不會(huì)設(shè)置成最低吉嚣。
因?yàn)榘踩?jí)別越高,處理效率就越低阻肿,但是安全級(jí)別越低瓦戚,危害就越大。
在數(shù)據(jù)庫(kù)中丛塌,可以通過
set transaction isolation level 設(shè)置事務(wù)隔離級(jí)別
select @@tx_isolation 查詢當(dāng)前事務(wù)隔離級(jí)別
兩條語句控制事務(wù)隔離級(jí)別较解。