數(shù)據(jù)庫事務和四種隔離級別

什么是事務

事務(Transaction):訪問并可能更新數(shù)據(jù)庫中各種數(shù)據(jù)項的一個程序執(zhí)行單元(unit)倚聚,它通常由高級數(shù)據(jù)庫操縱語言或編程語言(如SQL,C++或Java)書寫的用戶程序的執(zhí)行所引起啡氢。當在數(shù)據(jù)庫中更改數(shù)據(jù)成功時,在事務中更改的數(shù)據(jù)便會提交术裸,不再改變倘是。否則,事務就取消或者回滾袭艺,更改無效搀崭。

事務解釋:指要做的或所做的事情

事務本質:一系列操作

事務特性:事務是恢復和并發(fā)控制的基本單位。

例如 網(wǎng)上購物匹表,其交易過程至少包括以下幾個步驟的操作:
- 更改客戶所購商品的庫存信息门坷;
- 保存客戶付款信息宣鄙;
- 生成訂單并且保存到數(shù)據(jù)庫中袍镀;
- 更改用戶相關信息,例如購物數(shù)量等冻晤。

在正常情況下苇羡,這些操作都將順利進行,最終交易成功鼻弧,與交易相關的所有數(shù)據(jù)庫信息也成功地更新设江。但是锦茁,如果在執(zhí)行的途中遇到突然斷電或者其他意外情況,導致這一系列過程中任何一個環(huán)節(jié)出了差錯叉存,例如在更細商品庫存信息時發(fā)生異常码俩、顧客銀行賬戶余額不足等,都將導致整個交易過程失敗歼捏。而一旦失敗稿存,數(shù)據(jù)庫中所有信息都必須保持交易不影響數(shù)據(jù)庫的狀態(tài),即原有的庫存信息沒有被更新瞳秽、用戶也沒有付款瓣履、訂單也沒有生成。否則练俐,數(shù)據(jù)庫的信息將會不一致袖迎,或者出現(xiàn)更為嚴重的不可預測的后果。數(shù)據(jù)庫事務正是用來保證這種情況下交易的平穩(wěn)性和可預測性的技術腺晾。

事務的屬性

事務必須滿足四個屬性燕锥,即原子性(Atomicity)、一致性(Consistency)丘喻、隔離性(Isolation)脯宿、持久性(Durability),即ACID四種屬性泉粉。

(1)原子性

一個事務是一個不可分割的整體连霉,為了保證事務的總體目標,事務必須具有原子性嗡靡,即當數(shù)據(jù)修改時跺撼,要么全都執(zhí)行,要么全都不執(zhí)行讨彼。即歉井,不允許事務部分地完成,避免了只執(zhí)行這些操作的一部分而帶來的錯誤哈误。

(2)一致性

一個事務在執(zhí)行之前和執(zhí)行之后哩至,數(shù)據(jù)庫數(shù)據(jù)必須保持一致性。數(shù)據(jù)庫的一致性狀態(tài)應該滿足模式鎖指定的約束條件蜜自,那么在完整執(zhí)行該事務后菩貌,數(shù)據(jù)庫仍然處于一致性狀態(tài)。
例如:銀行轉賬重荠,轉賬前后兩個賬戶金額之和應保持不變箭阶。

(3)隔離性

由并發(fā)事務所作的修改必須與任何其它并發(fā)事務所作的修改隔離。事務查看數(shù)據(jù)庫時數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務修改它之前的狀態(tài)仇参,要么是另一事務修改它之后的狀態(tài)嘹叫,事務不會查看中間狀態(tài)的數(shù)據(jù)。
例如:對任何一對事務T1和T2诈乒,對T1而言罩扇,T2要么在T1開始之前已經(jīng)結束,要么在T1完成之后再開始執(zhí)行怕磨。

(4)持久性

也被稱為永久性暮蹂,事務完成以后,DBMS(數(shù)據(jù)庫管理系統(tǒng))保證它對數(shù)據(jù)庫中數(shù)據(jù)的修改是永久性的癌压,當系統(tǒng)或介質發(fā)生故障時仰泻,該修改也永久保持。持久性一般通過數(shù)據(jù)庫備份與恢復來保證滩届。

注意 嚴格而言集侯,數(shù)據(jù)庫事務屬性都是由數(shù)據(jù)庫管理系統(tǒng)來進行保證的,在整個應用程序的運行過程中帜消,應用程序無須去考慮數(shù)據(jù)庫的ACID實現(xiàn)棠枉。

一般情況下,通過執(zhí)行COMMIT(提交)或ROLLBACK(回滾)語句來終止事務泡挺。當執(zhí)行COMMIT語句時辈讶,自從事務啟動以來對數(shù)據(jù)庫所做的一切更改就成為永久性的,即被寫入到磁盤娄猫,而當執(zhí)行ROLLBACK語句時贱除,自從事務啟動以來對數(shù)據(jù)庫所做的一切更改都會被撤銷,并且數(shù)據(jù)庫中內容返回到事務開始之前所處的狀態(tài)媳溺。無論什么情況月幌,在事務完成時,都能保證回到一致性狀態(tài)悬蔽。

并發(fā)控制

(1)DBS(數(shù)據(jù)庫系統(tǒng))一個明顯的特點是多個用戶共享數(shù)據(jù)庫資源扯躺,尤其是多個用戶可以同時存取相同數(shù)據(jù)。

串行控制:如果事務是順序執(zhí)行的蝎困,即一個事務完成之后录语,再開始另一事務。
并行控制:如果DBMS可以同時接受多個事務禾乘,并且這些事務在時間上可以重疊執(zhí)行澎埠。

(2)并發(fā)控制概述

事務是并發(fā)控制的基本單位,保證事務ACID的特性是事務處理的重要任務盖袭,而并發(fā)操作有可能會破壞其ACID特性失暂。

DBMS并發(fā)控制機制的責任:對并發(fā)操作進行正確調度,保證事務的隔離更一般鳄虱,確保數(shù)據(jù)庫的一致性弟塞。

由于并發(fā)操作帶來的數(shù)據(jù)不一致性

如果沒有鎖定且多個用戶同時訪問一個數(shù)據(jù)庫,則當他們的事務同時使用相同的數(shù)據(jù)時可能會發(fā)生問題拙已。由于并發(fā)操作帶來的數(shù)據(jù)不一致性包括:丟失數(shù)據(jù)更新决记、讀“臟”數(shù)據(jù)(臟讀)、不可重復讀倍踪。

(1)更新丟失

兩個事務都同時更新一行數(shù)據(jù)系宫,一個事務對數(shù)據(jù)的更新把另一個事務對數(shù)據(jù)的更新覆蓋了。這是因為系統(tǒng)沒有執(zhí)行任何的鎖操作建车,因此并發(fā)并沒有被隔離開來扩借。

(2)臟讀

一個事務讀取到了另一事務未提交的數(shù)據(jù)操作結果。這是相當危險的缤至,因為很可能所有的操作都被回滾潮罪。

(3)不可重復讀

不可重復讀(Non-repeatable Reads):一個事務對同一行數(shù)據(jù)重復讀取兩次,但是卻得到了不同的結果领斥。包括以下情況:

虛讀:事務T1讀取某一數(shù)據(jù)后嫉到,事務T2對其做了修改,當事務T1再次讀取該數(shù)據(jù)時得到與前一次不同的值月洛。

幻讀:事務在操作過程中進行兩次查詢何恶,第二次查詢的結果包含了第一次查詢中未出現(xiàn)的數(shù)據(jù)或者缺少了第一次查詢中出現(xiàn)的數(shù)據(jù)。這是因為在兩次查詢過程中有另外一個事務插入數(shù)據(jù)造成的嚼黔。

事務隔離級別

為了避免上面出現(xiàn)的幾種情況细层,在標準SQL規(guī)范中,定義了4個事務隔離級別唬涧,不同的隔離級別對事務的處理不同今艺。

讀未提交(Read Uncommitted) 只處理更新丟失。 如果一個事務已經(jīng)開始寫數(shù)據(jù)爵卒,則不允許其他事務同時進行寫操作虚缎,但允許其他事務讀此行數(shù)據(jù)。 可通過“排他寫鎖”實現(xiàn)钓株。
讀已提交(Read Committed) 處理更新丟失实牡、臟讀。 讀取數(shù)據(jù)的事務允許其他事務繼續(xù)訪問改行數(shù)據(jù)轴合,但是未提交的寫事務將會禁止其他事務訪問改行创坞。 可通過“瞬間共享讀鎖”和“排他寫鎖”實現(xiàn)。
可重復讀仁芨稹(Repeatable Read) 處理更新丟失题涨、臟讀和不可重復讀取偎谁。 讀取數(shù)據(jù)的事務將會禁止寫事務,但允許讀事務纲堵,寫事務則禁止任何其他事務巡雨。 可通過“共享讀鎖”和“排他寫鎖”實現(xiàn)。
序列化(Serializable) 提供嚴格的事務隔離席函。 要求失去序列化執(zhí)行铐望,事務只能一個接一個地執(zhí)行,不能并發(fā)執(zhí)行茂附。 僅僅通過“行級鎖”是無法實現(xiàn)事務序列化的正蛙,必須通過其他機制保證新插入的數(shù)據(jù)不會被剛執(zhí)行查詢操作的事務訪問到。

隔離級別越高营曼,越能保證數(shù)據(jù)的完整性和統(tǒng)一性乒验,但是對并發(fā)性能的影響也越大。對于多數(shù)應用程序蒂阱,可以優(yōu)先考慮把數(shù)據(jù)庫系統(tǒng)的隔離級別設為Read Committed徊件。它能夠避免臟讀,而且具有較好的并發(fā)性能蒜危。盡管它會導致不可重復讀虱痕、幻讀和第二類丟失更新這些并發(fā)問題,在可能出現(xiàn)這類問題的個別場合辐赞,可以由應用程序采用悲觀鎖或樂觀鎖來控制部翘。

原文鏈接:https://blog.csdn.net/weixin_39651041/java/article/details/79980202

MySQl

MySql默認的隔離級別為Repeatable Read,因此只會出現(xiàn)幻讀的情況响委。

幻讀

事務在插入已經(jīng)檢查過不存在的記錄時新思,驚奇的發(fā)現(xiàn)這些數(shù)據(jù)已經(jīng)存在了,之前的檢測獲取到的數(shù)據(jù)如同鬼影一般赘风。

例子:
在事務1中夹囚,查詢User表id為1的是用戶否存在,如果不存在則插入一條id為1的數(shù)據(jù)邀窃。

select * from User where id = 1;

在事務1查詢結束后荸哟,事務2往User表中插入了一條id為1的數(shù)據(jù)。

insert intoUser(id,name) values (1, 'Joonwhee');
此時瞬捕,由于事務1查詢到id為1的用戶不存在鞍历,因此插入1條id為1的數(shù)據(jù)。

insert into ` User`(`id`, `name`) values (1, 'Chillax');

但是由于事務2已經(jīng)插入了1條id為1的數(shù)據(jù)肪虎,因此此時會報主鍵沖突劣砍,對于事務1 的業(yè)務來說是執(zhí)行失敗的,這里事務1 就是發(fā)生了幻讀扇救,因為事務1讀取的數(shù)據(jù)狀態(tài)并不能支持他的下一步的業(yè)務刑枝,見鬼了一樣香嗓。這里要靈活的理解讀取的意思,第一次select是讀取装畅,第二次的insert其實也屬于隱式的讀取靠娱,只不過是在mysql的機制中讀取的,插入數(shù)據(jù)也是要先讀取一下有沒有主鍵沖突才能決定是否執(zhí)行插入洁灵。

Oracle

Oracle默認的隔離級別為Read Committed,因此可能出現(xiàn)不可重復度和幻讀掺出。

不可重復讀

同樣的條件徽千,你讀取過的數(shù)據(jù),再次讀取出來發(fā)現(xiàn)值不一樣了汤锨。

例子:
在事務1中双抽,JoonWhee讀取了自己的工資為1000,但是此時事務1的操作還并沒有完成 闲礼,后面還有1次相同的讀取操作牍汹。

con1 = getConnection();  
select salary from employee where employeeName="JoonWhee";

在事務2中,這時財務人員修改了JoonWhee的工資為2000柬泽,并提交了事務慎菲。
con2 = getConnection(); update employee set salary = 2000 where employeeName = "JoonWhee"; con2.commit();
在事務1中,JoonWhee再次讀取自己的工資時锨并,工資變?yōu)榱?000 露该。

select salary from employee where employeeName ="JoonWhee"; 

在一個事務中前后兩次讀取的結果并不一致,導致了不可重復讀第煮。

幻讀

同樣的條件解幼,第1次和第2次讀出來的記錄數(shù)不一樣。

例子:
目前工資為1000的員工有10人包警。

事務1撵摆,讀取所有工資為1000的員工,共讀取10條記錄 害晦。

con1 = getConnection();  
Select * from employee where salary =1000;

這時另一個事務向employee表插入了一條員工記錄特铝,工資也為1000
con2 = getConnection(); Insert into employee(employeeName,salary) values("Lili",1000); con2.commit();
事務1再次讀取所有工資為1000的員工,共讀取到了11條記錄壹瘟,這就產(chǎn)生了幻讀苟呐。

    select * from employee where salary =1000;

原文鏈接:https://blog.csdn.net/v123411739/java/article/details/39298127

擴展閱讀:

數(shù)據(jù)庫ACID解道

數(shù)據(jù)庫的分區(qū):水平分區(qū)、垂直分區(qū)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末俐筋,一起剝皮案震驚了整個濱河市牵素,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澄者,老刑警劉巖笆呆,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件请琳,死亡現(xiàn)場離奇詭異,居然都是意外死亡赠幕,警方通過查閱死者的電腦和手機俄精,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來榕堰,“玉大人竖慧,你說我怎么就攤上這事∧媛牛” “怎么了圾旨?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長魏蔗。 經(jīng)常有香客問我砍的,道長,這世上最難降的妖魔是什么莺治? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任廓鞠,我火速辦了婚禮,結果婚禮上谣旁,老公的妹妹穿的比我還像新娘床佳。我一直安慰自己,他們只是感情好榄审,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布夕土。 她就那樣靜靜地躺著,像睡著了一般瘟判。 火紅的嫁衣襯著肌膚如雪怨绣。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天拷获,我揣著相機與錄音,去河邊找鬼匆瓜。 笑死赢笨,一個胖子當著我的面吹牛,可吹牛的內容都是我干的驮吱。 我是一名探鬼主播茧妒,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼左冬!你這毒婦竟也來了桐筏?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤拇砰,失蹤者是張志新(化名)和其女友劉穎梅忌,沒想到半個月后狰腌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡牧氮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年琼腔,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片踱葛。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡丹莲,死狀恐怖,靈堂內的尸體忽然破棺而出尸诽,到底是詐尸還是另有隱情甥材,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布逊谋,位于F島的核電站擂达,受9級特大地震影響土铺,放射性物質發(fā)生泄漏胶滋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一悲敷、第九天 我趴在偏房一處隱蔽的房頂上張望究恤。 院中可真熱鬧,春花似錦后德、人聲如沸部宿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽理张。三九已至,卻和暖如春绵患,著一層夾襖步出監(jiān)牢的瞬間雾叭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工落蝙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留织狐,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓筏勒,卻偏偏與公主長得像移迫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子管行,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內容