事務是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;
原文地址:http://blog.sina.com.cn/s/blog_4c197d420101awhc.html