事務是訪問資料庫的乙個操作序列,資料庫應用系統通過事務集來完成對資料庫的訪問。事務的正確執行使得資料庫從一種狀態轉換為另一種狀態。
事務必須服從iso/iec所制定的acid原則。acid是原子性(atomicity)、一致性(consistency)、隔離性(isolation)、永續性(durability)的縮寫,這四種狀態的意思是:
即不可分割,事務要麼全部被執行,要麼全部不執行。如果事務的所有子事務全部提交成功,則所有的資料庫操作被提交,資料庫狀態發生變化;如果有子事務失敗,則其他子事務的資料庫操作被回滾,即資料庫回到事務執行前的狀態,不會發生狀態轉換.
事務的執行使得資料庫從一種正確狀態轉換成另外一種正確狀態
在事務正確提交之前,不允許把事務對該資料的改變提供給任何其他事務,即在事務正確提交之前,它可能的結果不應該顯示給其他事務
事務正確提交之後,其結果將永遠儲存在資料庫之中,即使在事務提交之後有了其他故障,事務的處理結果也會得到儲存
事務管理對於企業級應用而言至關重要,它保證了使用者的每一次操作都是可靠的,即便出現了異常的訪問情況,也不至於破壞後台資料的完整性。
舉個例子,事務a和事務b操縱的是同乙個資源,事務a有若干個子事務,事務b也有若干個子事務,事務a和事務b在高併發的情況下,會出現各種各樣的問題。「各種各樣的問題」,總結一下主要就是五種:第一類丟失更新、第二類丟失更新、髒讀、不可重複讀、幻讀。五種之中,第一類丟失更新、第二類丟失更新不重要,講一下髒讀、不可重複讀和幻讀。
所謂髒讀,就是指事務a讀到了事務b還沒有提交的資料,就比如考試作弊,小明抄了小紅的試卷,以為這就是答案然後就交卷了,結果小紅發現自己的答案有點問題,然後改了一下再提交,小明讀到的就是髒資料,這就是髒讀。
所謂不可重複讀,就是指在乙個事務裡面讀取了兩次某個資料,讀出來的資料不一致。還是以銀行取錢為例,事務a開啟事務–>查出銀行卡餘額為1000元,此時切換到事務b事務b開啟事務–>事務b取走100元–>提交,資料庫裡面餘額變為900元,此時切換回事務a,事務a再查一次查出賬戶餘額為900元,這樣對事務a而言,在同乙個事務內兩次讀取賬戶餘額資料不一致,這就是不可重複讀。
所謂幻讀,就是指在乙個事務裡面的操作中發現了未被操作的資料。比如學生資訊,事務a開啟事務–>修改所有學生當天簽到狀況為false,此時切換到事務b,事務b開啟事務–>事務b插入了一條學生資料,此時切換回事務a,事務a提交的時候發現了一條自己沒有修改過的資料,這就是幻讀,就好像發生了幻覺一樣。幻讀出現的前提是併發的事務中有事務發生了插入、刪除操作。
事務隔離級別,就是為了解決上面幾種問題而誕生的。為什麼要有事務隔離級別,因為事務隔離級別越高,在併發下會產生的問題就越少,但同時付出的效能消耗也將越大,因此很多時候必須在併發性和效能之間做乙個權衡。所以設立了幾種事務隔離級別,以便讓不同的專案可以根據自己專案的併發情況選擇合適的事務隔離級別,對於在事務隔離級別之外會產生的併發問題,在**中做補償。
事務隔離級別有4種,但是像spring會提供給使用者5種,來看一下:
預設隔離級別,每種資料庫支援的事務隔離級別不一樣,如果spring配置事務時將isolation設定為這個值的話,那麼將使用底層資料庫的預設事務隔離級別。順便說一句,如果使用的mysql,可以使用"select @@tx_isolation"來檢視預設的事務隔離級別,mysql預設為repeatable_read,oracle預設為read_commited.
讀未提交,即能夠讀取到沒有被提交的資料,所以很明顯這個級別的隔離機制無法解決髒讀、不可重複讀、幻讀中的任何一種,因此很少使用
讀已提交,即能夠讀到那些已經提交的資料,自然能夠防止髒讀,但是無法限制不可重複讀和幻讀
重複讀取,即在資料讀出來之後加鎖,類似"select * from *** for update",明確資料讀取出來就是為了更新用的,所以要加一把鎖,防止別人修改它。repeatable_read的意思也類似,讀取了一條資料,這個事務不結束,別的事務就不可以改這條記錄,這樣就解決了髒讀、不可重複讀的問題,但是幻讀的問題還是無法解決
序列化,最高的事務隔離級別,不管多少事務,挨個執行完乙個事務的所有子事務之後才可以執行另外乙個事務裡面的所有子事務,這樣就解決了髒讀、不可重複讀和幻讀的問題了
隔離級別
髒讀可能性
不可重複讀可能性
幻讀可能性
加鎖讀read_uncommitted是是
是否read_commited否是
是否repeatable_read否否
是是serlalizable否否
否是首先說明一下mysql檢視和修改事務隔離級別的幾個命令:
檢視事務隔離級別使用select @@tx_isolation
修改當前會話事務隔離級別使用set session transaction isolation level serializable;(引數可以為:read uncommitted|read committed|repeatable read|serializable)
修改全域性事務隔離級別使用set global transaction isolation level serializable;(引數可以為:read uncommitted|read committed|repeatable read|serializable)
修改了會話的事務隔離級別,比如mybatis,getsqlsession()的時候,只針對這一次拿到的session有效;比如cmd命令列,只對這一次的視窗有效。
修改了全域性的事務隔離級別,那麼針對此後所有的會話有效,當前已經存在的會話不受影響。
關於mysql事務隔離級別,推薦大家一篇文章,很詳細地測試了四種事務隔離級別相信大家讀了一定有所進步。
事務及事務隔離級別
什麼是事務 事務是訪問資料庫的乙個操作序列,資料庫應用系統通過事務集來完成對資料庫的訪問。事務的正確執行使得資料庫從一種狀態轉換為另一種狀態。事務必須服從iso iec所制定的acid原則。acid是原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 du...
事務及事務隔離級別
事務是訪問資料庫的乙個操作序列,資料庫應用系統通過事務集來完成對資料庫的訪問。事務的正確執行使得資料庫從一種狀態轉換為另一種狀態。事務必須服從iso iec所制定的acid原則。acid是原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 durabili...
事務及隔離級別
事務是由乙個或者一組sql組成的執行單元。事務具有acid特性 atomicity 原子性 同乙個事務裡要麼全部提交,要麼全部回滾,不能只有一部分成功或者一部分回滾。如果在事務執行過程 中發生了錯誤,那麼就要通過undo log將事務回滾到開始時的狀態。consistency 一致性 事務和資料要保...