關於MySQL的事務處理及隔離級別


原文地址 :http://blog.sina.com.cn/s/blog_4c197d420101awhc.html

 

事務是DBMS得執行單位。它由有限得數據庫操作序列組成得。但不是任意得數據庫操作序列都能成為事務。一般來說,事務是必須滿足4個條件(ACID)
       原子性(Autmic):事務在執行性,要做到“要么不做,要么全做!”,就是說不允許事務部分得執行。即使因為故障而使事務不能完成,在rollback時也要消除對數據庫得影響!
       一致性(Consistency):事務操作之后,數據庫所處的狀態和業務規則是一致的;比如a,b賬戶相互轉賬之后,總金額不變!
      隔離性(Isolation):如果多個事務並發執行,應像各個事務獨立執行一樣!
      持久性(Durability):事務提交后被持久化到數據庫.
MYSQL的事務處理主要有兩種方法。
   1、用BEGIN,ROLLBACK,COMMIT來實現
      開始:START TRANSACTION或BEGIN語句可以開始一項新的事務
      提交:COMMIT可以提交當前事務,是變更成為永久變更
      回滾:ROLLBACK可以回滾當前事務,取消其變更
   2、直接用set來改變mysql的自動提交模式
       MYSQL默認是自動提交的,也就是你提交一個QUERY,它就直接執行!
  我們可以通過set autocommit=0 禁止自動提交
              set autocommit=1 開啟自動提交
       來實現事務的處理。
       但注意當你用 set autocommit=0 的時候,你以后所有的SQL都將做為事務處理,直到你用commit確認或rollback結束,並且 只用於當前連接
    ※ MYSQL中只有INNODB和BDB類型的數據表才能支持事務處理!其他的類型是不支持!
 
自己的理解(關於更新丟失,臟讀,不可重復讀,幻讀)
       更新丟失:
   當兩個或多個事務選擇同一行,然后基於最初選定的值更新該行時,由於每個事務都不知道其他事務的存在,就會發生丟失更新問題--最后的更新覆蓋了由其他事務所做的更新。例如,兩個編輯人員制作了同一文檔的電子副本。每個編輯人員獨立地更改其副本,然后保存更改后的副本,這樣就覆蓋了原始文檔。最后保存其更改副本的編輯人員覆蓋另一個編輯人員所做的更改。如果在一個編輯人員完成並提交事務之前,另一個編輯人員不能訪問同一文件,則可避免此問題。
  ※臟讀:一個事務讀取了另一個未提交的並行事務寫的數據。
      (事務T1更新了一行記錄的內容,但是並沒有提交所做的修改。事務T2讀取更新后的行,然后T1執行回滾操作,取消了剛才所做的修改。現在T2所讀取的行就無效了。)
      
      exp:
      小明的分數為89,事務A中把他的分數改為98,但事務A尚未提交。
      與此同時,
      事務B正在讀取小明的分數,讀取到小明的分數為98。
      隨后,
      事務A發生異常,而回滾了事務。小明的分數又回滾為89。
      最后,
      事務B讀取到的小明的分數為98的數據即為臟數據,事務B做了一次臟讀。
      (大部分數據庫缺省的事物隔離級別都不會出現這種狀況)
      
      ※不可重復讀:一個事務重新讀取前面讀取過的數據,發現該數據已經被另一個已提交的事務修改過。
      (事務T1讀取一行記錄,緊接着事務T2修改了T1剛才讀取的那一行記錄。然后T1又再次讀取這行記錄,發現與剛才讀取的結果不同。這就稱為“不可重復”讀,因為T1原來讀取的那行記錄已經發生了變化。)
      exp:
      在事務A中,讀取到小明的分數為89,操作沒有完成,事務還沒提交。
      與此同時,
      事務B把小明的分數改為98,並提交了事務。
      隨后,
      在事務A中,再次讀取小明的分數,此時工資變為98。在一個事務中前后兩次讀取的結果並不致,導致了不可重復讀。
 
      ※幻讀:一個事務重新執行一個查詢,返回一套符合查詢條件的行,發現這些行因為其他最近提交的事務而發生了改變。
      (事務T1讀取一條指定的WHERE子句所返回的結果集。然后事務T2新插入 一行記錄,這行記錄恰好可以滿足T1所使用的查詢條件中的WHERE 子句的條件。然后T1又使用相同的查詢再次對表進行檢索,但是此時卻看到了事務T2剛才插入的新行。這個新行就稱為“幻像”,因為對T1來說這一行就像突 然出現的一樣。)
      exp:
      目前分數為90分以上的的學生有15人,事務A讀取所有分數為90分以上的的學生人數有15人。
      此時,事務B插入一條分數為99的學生記錄。
      這是,事務A再次讀取90分以上的的學生,記錄為16人。此時產生了幻讀。
      (大部分數據庫缺省的事物隔離級別都會出現這種狀況,此種事物隔離級別將帶來表級鎖)
 
在上面講到的並發事務處理帶來的問題中,“更新丟失”通常是應該完全避免的。但防止更新丟失,並不能單靠數據庫事務控制器來解決,需要應用程序對要更新的數據加必要的鎖來解決,因此,防止更新丟失應該是應用的責任。(版本號控制)
“臟讀”、“不可重復讀”和“幻讀”,其實都是數據庫讀一致性問題,必須由數據庫提供一定的事務隔離機制來解決。
 
事務隔離級別描述:
      READ UNCOMMITTED:幻讀,不可重復讀和臟讀均允許;
      READ COMMITTED:允許幻讀和不可重復讀,但不允許臟讀;
      REPEATABLE READ:允許幻讀,但不允許不可重復讀和臟讀;
      SERIALIZABLE:幻讀,不可重復讀和臟讀都不允許; 
      ORACLE默認的是 READ COMMITTED。
      MYSQL默認的是 REPEATABLE READ。
      
      如果數據庫的隔離級別為REAE_UNCOMMITTED, 則其他線程可以看到未提交的數據, 因此就出現臟讀;
      如果數據庫隔離級別設為READ_COMMITTED,即沒提交的數據別人是看不見的,就避免了臟讀;但是,正在讀取的數據只獲得了讀取鎖,讀完之后就解鎖,不管當前事務有沒有結束,這樣就容許其他事務修改本事務正在讀取的數據。導致不可重復讀。
      REPEATABLE READ因為對正在操作的數據加鎖,並且只有等到事務結束才放開鎖, 則可以避免不可重復讀;
      REPEATABLE READ只能保證正在被本事務操作的數據不被其他事務修改,卻無法保證有其他事務提交新的數據。 則有可能線程1在操作表T1的時候(特別是統計性的事務),其他線程仍然可以提交新數據到表T1,這樣會導致線程1兩次統計的結果不一致,就像發生幻覺一樣。
      SERIALIZABLE因為獲得范圍鎖,且事務是一個接着一個串行執行,則保證了不會發生幻讀。
      由此可見,隔離級別越高,受其他事物干擾越少,並發性能越差。
 
      二個或以上事務在操作同一個共享記錄集時,可能會出現的問題:
      (A)臟讀 (B)不可重復讀 (C)幻讀
      隔離級別:
      (1)read-uncommit, (2)read-commit, (3)read-repeatable, (4)read-serializable
      都是用來阻止上面的問題的,其中:
      (1)什么都阻止不了。
      (2)阻止(A)
      (3)阻止(A)(B)
      (4)阻止(A)(B)(C)
      (1)->(4)隔離級別越高,性能損失越大。
 
修改事務的隔離級別:
      在MySQL中默認事務隔離級別是可重復讀(Repeatable read).可通過SQL語句查詢:
      查看InnoDB系統級別的事務隔離級別:
      mysql> SELECT @@global.tx_isolation;
 
      結果:
      +-----------------------+
      | @@global.tx_isolation |
      +-----------------------+
      | REPEATABLE-READ       |
      +-----------------------+
 
      查看InnoDB會話級別的事務隔離級別:
      mysql> SELECT @@tx_isolation;
 
      結果:
      +-----------------+
      | @@tx_isolation  |
      +-----------------+
      | REPEATABLE-READ |
      +-----------------+
 
      修改事務隔離級別:
      mysql> set global transaction isolation level read committed;
      mysql> set session transaction isolation level read committed;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM