什麼是事務?事務的四個特性以及事務的隔離級別

什麼是事務程序員

  事務是指是程序中一系列嚴密的邏輯操做,並且全部操做必須所有成功完成,不然在每一個操做中所做的全部更改都會被撤消。能夠通俗理解爲:就是把多件事情當作一件事情來處理,比如你們同在一條船上,要活一塊兒活,要完一塊兒完 。sql

 

事物的四個特性(ACID)數據庫

  ● 原子性(Atomicity)操做這些指令時,要麼所有執行成功,要麼所有不執行。只要其中一個指令執行失敗,全部的指令都執行失敗,數據進行回滾,回到執行指令前的數據狀態。併發

eg:拿轉帳來講,假設用戶A和用戶B二者的錢加起來一共是20000,那麼無論A和B之間如何轉帳,轉幾回帳,事務結束後兩個用戶的錢相加起來應該還得是20000,這就是事務的一致性。性能

  ● 一致性(Consistency)事務的執行使數據從一個狀態轉換爲另外一個狀態,可是對於整個數據的完整性保持穩定。spa

  ● 隔離性(Isolation)隔離性是當多個用戶併發訪問數據庫時,好比操做同一張表時,數據庫爲每個用戶開啓的事務,不能被其餘事務的操做所幹擾,多個併發事務之間要相互隔離。對象

              即要達到這麼一種效果:對於任意兩個併發的事務T1和T2,在事務T1看來,T2要麼在T1開始以前就已經結束,要麼在T1結束以後纔開始,這樣每一個事務都感受不到有其餘事務在併發地執行。事務

  ● 持久性(Durability)當事務正確完成後,它對於數據的改變是永久性的。ip

eg: 例如咱們在使用JDBC操做數據庫時,在提交事務方法後,提示用戶事務操做完成,當咱們程序執行完成直到看到提示後,就能夠認定事務以及正確提交,即便這時候數據庫出現了問題,也必需要將咱們的事務徹底執行完成,不然就會形成咱們看到提示事務處理完畢,可是數據庫由於故障而沒有執行事務的重大錯誤。ci

 

併發事務致使的問題

  在許多事務處理同一個數據時,若是沒有采起有效的隔離機制,那麼併發處理數據時,會帶來一些的問題。

  ● 第一類丟失更新:撤銷一個事務時,把其餘事務已提交的更新數據覆蓋。

eg:小明去銀行櫃檯存錢,他的帳戶裏原來的餘額爲100元,如今打算存入100元。在他存錢的過程當中,銀行年費扣了5元,餘額只剩95元。忽然他又想着這100元要用來請女友看電影吃飯,不打算存了。在他撤回存錢操做後,餘額依然爲他存錢以前的100元。因此那5塊錢到底扣了誰的?

  

   髒讀:髒讀是指在一個事務處理過程裏讀取了另外一個未提交的事務中的數據。

eg:小明的銀行卡餘額裏有100元。如今他打算用手機點一個外賣飲料,須要付款10元。可是這個時候,他的女友看中了一件衣服95元,她正在使用小明的銀行卡付款。因而小明在付款的時候,程序後臺讀取到他的餘額只有5塊錢了,根本不夠10元,因此係統拒絕了他的交易,告訴餘額不足。可是小明的女友最後由於密碼錯誤,沒法進行交易。小明很是鬱悶,明明銀行卡里還有100元,怎麼會餘額不足呢?(他女友更鬱悶。。。)

 

   幻讀也叫虛讀:一個事務執行兩次查詢,第二次結果集包含第一次中沒有或某些行已經被刪除的數據,形成兩次結果不一致,只是另外一個事務在這兩次查詢中間插入或刪除了數據形成的。幻讀是事務非獨立執行時發生的一種現象。

eg:例如事務T1對一個表中全部的行的某個數據項作了從「1」修改成「2」的操做,這時事務T2又對這個表中插入了一行數據項,而這個數據項的數值仍是爲「1」而且提交給數據庫。而操做事務T1的用戶若是再查看剛剛修改的數據,會發現還有一行沒有修改,其實這行是從事務T2中添加的,就好像產生幻覺同樣,這就是發生了幻讀。

 

   不可重複讀:一個事務兩次讀取同一行的數據,結果獲得不一樣狀態的結果,中間正好另外一個事務更新了該數據,兩次結果相異,不可被信任。

eg:例如事務T1在讀取某一數據,而事務T2立馬修改了這個數據而且提交事務給數據庫,事務T1再次讀取該數據就獲得了不一樣的結果,發送了不可重複讀。

Tips:不可重複讀和髒讀的區別:髒讀是某一事務讀取了另外一個事務未提交的髒數據,而不可重複讀則是讀取了前一事務提交的數據。 

Tips:幻讀和不可重複讀都是讀取了另外一條已經提交的事務(這點就髒讀不一樣),所不一樣的是不可重複讀查詢的都是同一個數據項,而幻讀針對的是一批數據總體(好比數據的個數)。

 

  ● 第二類丟失更新:是不可重複讀的特殊狀況。若是兩個事物都讀取同一行,而後兩個都進行寫操做,並提交,第一個事物所作的改變就會丟失。

eg:小明和女友一塊兒去逛街。女友看中了一支口紅,(對,女友就是用來表現買買買的)小明大方的掏出了本身的銀行卡,告訴女友:親愛的,隨便刷,隨便買,我坐着等你。而後小明就坐在商城座椅上玩手機,等着女友。這個時候,程序員的聊天羣裏有人推薦了一本書,小明一看,哎呀,真是本好書,仍是限量發行呢,我必定更要買到。因而小明趕忙找到購買渠道,進行付款操做。而同時,小明的女友也在不亦樂乎的買買買,他們同時進行了一筆交易操做,可是這個時候銀行系統出了問題,當他們都付款成功後,卻發現,銀行只扣了小明的買書錢,卻沒有扣去女友此時交易的錢。哈哈哈,小明真是太開心了!

 

數據庫事務的隔離級別

  事務的隔離級別有4種,由低到高分別爲Read uncommittedRead committedRepeatable readSerializable 。並且,在事務的併發操做中可能會出現髒讀不可重複讀幻讀。下面經過事例一一闡述它們的概念與聯繫。

Read uncommitted(最低級別,任何狀況都沒法保證。)

讀未提交,顧名思義,就是一個事務能夠讀取另外一個未提交事務的數據。

eg:老闆要給程序員發工資,程序員的工資是3.6萬/月。可是發工資時老闆不當心按錯了數字,按成3.9萬/月,該錢已經打到程序員的戶口,可是事務尚未提交,就在這時,程序員去查看本身這個月的工資,發現比往常多了3千元,覺得漲工資了很是高興。可是老闆及時發現了不對,立刻回滾差點就提交了的事務,將數字改爲3.6萬再提交。

Analyse:實際程序員這個月的工資仍是3.6萬,可是程序員看到的是3.9萬。他看到的是老闆還沒提交事務時的數據。這就是髒讀。

那怎麼解決髒讀呢?Read committed!讀提交,能解決髒讀問題。 

 

Read committed(可避免髒讀的發生。)

讀提交,顧名思義,就是一個事務要等另外一個事務提交後才能讀取數據。

eg:程序員拿着信用卡去享受生活(卡里固然是隻有3.6萬),當他埋單時(程序員事務開啓),收費系統事先檢測到他的卡里有3.6萬,就在這個時候!!程序員的妻子要把錢所有轉出充當家用,並提交。當收費系統準備扣款時,再檢測卡里的金額,發現已經沒錢了(第二次檢測金額固然要等待妻子轉出金額事務提交完)。程序員就會很鬱悶,明明卡里是有錢的…

Analyse:這就是讀提交,如有事務對數據進行更新(UPDATE)操做時,讀操做事務要等待這個更新操做事務提交後才能讀取數據,能夠解決髒讀問題。但在這個事例中,出現了一個事務範圍內兩個相同的查詢卻返回了不一樣數據,這就是不可重複讀。

那怎麼解決可能的不可重複讀問題?Repeatable read !

 

Repeatable read(可避免髒讀、不可重複讀的發生。)

重複讀,就是在開始讀取數據(事務開啓)時,再也不容許修改操做

eg:程序員拿着信用卡去享受生活(卡里固然是隻有3.6萬),當他埋單時(事務開啓,不容許其餘事務的UPDATE修改操做),收費系統事先檢測到他的卡里有3.6萬。這個時候他的妻子不能轉出金額了。接下來收費系統就能夠扣款了。

Analyse:重複讀能夠解決不可重複讀問題。寫到這裏,應該明白的一點就是,不可重複讀對應的是修改,即UPDATE操做。可是可能還會有幻讀問題。由於幻讀問題對應的是插入INSERT操做,而不是UPDATE操做。

何時會出現幻讀?

eg:程序員某一天去消費,花了2千元,而後他的妻子去查看他今天的消費記錄(全表掃描FTS,妻子事務開啓),看到確實是花了2千元,就在這個時候,程序員花了1萬買了一部電腦,即新增INSERT了一條消費記錄,並提交。當妻子打印程序員的消費記錄清單時(妻子事務提交),發現花了1.2萬元,彷佛出現了幻覺,這就是幻讀。

那怎麼解決幻讀問題?Serializable!

 

Serializable(可避免髒讀、不可重複讀、幻讀的發生。) 序列化

Serializable 是最高的事務隔離級別,在該級別下,事務串行化順序執行,能夠避免髒讀、不可重複讀與幻讀。可是這種事務隔離級別效率低下,比較耗數據庫性能,通常不使用。

Tips:大多數數據庫默認的事務隔離級別是Read committed,好比Sql Server , Oracle。

    Mysql的默認隔離級別是Repeatable read。

Tips隔離級別的設置只對當前連接有效。對於使用MySQL命令窗口而言,一個窗口就至關於一個連接,當前窗口設置的隔離級別只對當前窗口中的事務有效;對於JDBC操做數據庫來講,一個Connection對象至關於一個連接,而對於Connection對象設置的隔離級別只對該Connection對象有效,與其餘連接Connection對象無關。

Tips設置數據庫的隔離級別必定要是在開啓事務以前

相關文章
相關標籤/搜索