什麼是事務
html
事務是訪問數據庫的一個操做序列,數據庫應用系統經過事務集來完成對數據庫的存取。事務的正確執行使得數據庫從一種狀態轉換爲另外一種狀態。數據庫
事務必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)、持久性(durability)的縮寫,這四種狀態的意思是:session
一、原子性併發
即不可分割,事務要麼所有被執行,要麼所有不執行。若是事務的全部子事務所有提交成功,則全部的數據庫操做被提交,數據庫狀態發生變化;若是有子事務失敗,則其餘子事務的數據庫操做被回滾,即數據庫回到事務執行前的狀態,不會發生狀態轉換高併發
二、一致性性能
事務的執行使得數據庫從一種正確狀態轉換成另一種正確狀態測試
三、隔離性atom
在事務正確提交以前,不容許把事務對該數據的改變提供給任何其餘事務,即在事務正確提交以前,它可能的結果不該該顯示給其餘事務spa
四、持久性命令行
事務正確提交以後,其結果將永遠保存在數據庫之中,即便在事務提交以後有了其餘故障,事務的處理結果也會獲得保存
事務的做用
事務管理對於企業級應用而言相當重要,它保證了用戶的每一次操做都是可靠的,即使出現了異常的訪問狀況,也不至於破壞後臺數據的完整性。就像銀行的自動提款機ATM,一般ATM均可以正常爲客戶服務,可是也不免遇到操做過程當中及其忽然出故障的狀況,此時,事務就必須確保出故障前對帳戶的操做不生效,就像用戶剛纔徹底沒有使用過ATM機同樣,以保證用戶和銀行的利益都不受損失。
併發下事務會產生的問題
舉個例子,事務A和事務B操縱的是同一個資源,事務A有若干個子事務,事務B也有若干個子事務,事務A和事務B在高併發的狀況下,會出現各類各樣的問題。"各類各樣的問題",總結一下主要就是五種:第一類丟失更新、第二類丟失更新、髒讀、不可重複讀、幻讀。五種之中,第一類丟失更新、第二類丟失更新不重要,不講了,講一下髒讀、不可重複讀和幻讀。
一、髒讀
所謂髒讀,就是指事務A讀到了事務B尚未提交的數據,好比銀行取錢,事務A開啓事務,此時切換到事務B,事務B開啓事務-->取走100元,此時切換回事務A,事務A讀取的確定是數據庫裏面的原始數據,由於事務B取走了100塊錢,並無提交,數據庫裏面的帳務餘額確定仍是原始餘額,這就是髒讀。
二、不可重複讀
所謂不可重複讀,就是指在一個事務裏面讀取了兩次某個數據,讀出來的數據不一致。仍是以銀行取錢爲例,事務A開啓事務-->查出銀行卡餘額爲1000元,此時切換到事務B事務B開啓事務-->事務B取走100元-->提交,數據庫裏面餘額變爲900元,此時切換回事務A,事務A再查一次查出帳戶餘額爲900元,這樣對事務A而言,在同一個事務內兩次讀取帳戶餘額數據不一致,這就是不可重複讀。
三、幻讀
所謂幻讀,就是指在一個事務裏面的操做中發現了未被操做的數據。好比學生信息,事務A開啓事務-->修改全部學生當天簽到情況爲false,此時切換到事務B,事務B開啓事務-->事務B插入了一條學生數據,此時切換回事務A,事務A提交的時候發現了一條本身沒有修改過的數據,這就是幻讀,就好像發生了幻覺同樣。幻讀出現的前提是併發的事務中有事務發生了插入、刪除操做。
事務隔離級別
事務隔離級別,就是爲了解決上面幾種問題而誕生的。爲何要有事務隔離級別,由於事務隔離級別越高,在併發下會產生的問題就越少,但同時付出的性能消耗也將越大,所以不少時候必須在併發性和性能之間作一個權衡。因此設立了幾種事務隔離級別,以便讓不一樣的項目能夠根據本身項目的併發狀況選擇合適的事務隔離級別,對於在事務隔離級別以外會產生的併發問題,在代碼中作補償。
事務隔離級別有4種,可是像Spring會提供給用戶5種,來看一下:
一、DEFAULT
默認隔離級別,每種數據庫支持的事務隔離級別不同,若是Spring配置事務時將isolation設置爲這個值的話,那麼將使用底層數據庫的默認事務隔離級別。順便說一句,若是使用的MySQL,可使用"select @@tx_isolation"來查看默認的事務隔離級別
二、READ_UNCOMMITTED
讀未提交,即可以讀取到沒有被提交的數據,因此很明顯這個級別的隔離機制沒法解決髒讀、不可重複讀、幻讀中的任何一種,所以不多使用
三、READ_COMMITED
讀已提交,即可以讀到那些已經提交的數據,天然可以防止髒讀,可是沒法限制不可重複讀和幻讀
四、REPEATABLE_READ
重複讀取,即在數據讀出來以後加鎖,相似"select * from XXX for update",明確數據讀取出來就是爲了更新用的,因此要加一把鎖,防止別人修改它。REPEATABLE_READ的意思也相似,讀取了一條數據,這個事務不結束,別的事務就不能夠改這條記錄,這樣就解決了髒讀、不可重複讀的問題,可是幻讀的問題仍是沒法解決
五、SERLALIZABLE
串行化,最高的事務隔離級別,無論多少事務,挨個運行完一個事務的全部子事務以後才能夠執行另一個事務裏面的全部子事務,這樣就解決了髒讀、不可重複讀和幻讀的問題了
網上專門有圖用表格的形式列出了事務隔離級別解決的併發問題:
再必須強調一遍,不是事務隔離級別設置得越高越好,事務隔離級別設置得越高,意味着勢必要花手段去加鎖用以保證事務的正確性,那麼效率就要下降,所以實際開發中每每要在效率和併發正確性之間作一個取捨,通常狀況下會設置爲READ_COMMITED,此時避免了髒讀,併發性也還不錯,以後再經過一些別的手段去解決不可重複讀和幻讀的問題就行了。
事物隔離級別查看及修改
首先說明一下MySQL查看和修改事務隔離級別的幾個命令:
修改了會話的事務隔離級別,好比MyBatis,getSqlSession()的時候,只針對這一次拿到的Session有效;好比CMD命令行,只對這一次的窗口有效。
修改了全局的事務隔離級別,那麼針對此後全部的會話有效,當前已經存在的會話不受影響。
關於MySQL事務隔離級別,推薦你們一篇文章,很詳細地測試了四種事務隔離級別https://www.cnblogs.com/snsdzjlz320/p/5761387.html,相信你們讀了必定有所進步。