最近銀行這個事情鬧的比較厲害啊,很多儲戶的錢放在銀行,就不翼而飛了,而銀行還不管不問,說是用戶的責任,打官司,用戶還能輸了,這就是“社會主義”。咱還是少發牢騷,多種樹,莫談國事。
說到銀行存錢,就不得不說一下從銀行取錢這件事情,從ATM機取錢這件簡單的事情,實際上主要分為以下幾個步驟:
一個簡單的取錢,主要分為以上幾步。不知道大家有沒有“天真”的想過,如果在第5步中,後台數據庫中已經把錢減掉了,但是ATM還就是沒有吐出錢(雖然實際也發生過,但是畢竟是低概率事件),這該怎麼辦?
關於這個問題,銀行系統的開發人員早就想過了,那麼他們是怎麼來搞定這個問題的呢?這就要說到今天總結的事務這個概念了。
對於上面的取錢這個事情,如果有一步出現了錯誤,那麼就取消整個取錢的動作;簡單來說,就是取錢這7步,要麼都完成,要麼就啥也不做。在數據庫中,事務也是這個道理。
事務由一條或者多條sql語句組成,在事務中的操作,這些sql語句要麼都執行,要麼都不執行,這就是事務的目的。
對於事務而言,它需要滿足ACID特性,下面就簡要的說說事務的ACID特性。
總結了一些事務的基本概念,在MySQL中,事務還是分為很多中的,下面就來看看到底有哪些事務。
你能想象到嗎?就這麼個破事務還會分以下這麼多種:
現在就來對這些事務從概念的層面上進行簡單的總結一下。
BEGIN WORK
Operation 1
Operation 2
Operation 3
...
Operation N
COMMIT WORK
或者是這種:
BEGIN WORK
Operation 1
Operation 2
Operation 3
...
Operation N
(Error Occured)
ROLLBACK WORK
扁平事務的主要缺點是不能提交或回滾事務的某一部分,或者分幾個獨立的步驟去提交。比如有這樣的一個例子,我從呼和浩特去深圳,為了便宜,我可能這麼干:
BEGIN WORK
Operation1:呼和浩特---火車--->北京
Operation2:北京---飛機--->深圳
ROLLBACK WORK
但是,如果Operation1,從呼和浩特到北京的火車晚點了,錯過了航班,怎麼辦?感覺扁平事務的特性,那我就需要回滾,我再回到呼和浩特,那麼這樣成本是不是也太高了啊,所以就有了下面的第二種事務——帶有保存點的扁平事務。
BEGIN WORK
SubTransaction1:
BEGIN WORK
SubOperationX
COMMIT WORK
SubTransaction2:
BEGIN WORK
SubOperationY
COMMIT WORK
...
SubTransactionN:
BEGIN WORK
SubOperationN
COMMIT WORK
COMMIT WORK
這就是嵌套事務,在事務中再嵌套事務,位於根節點的事務稱為頂層事務。事務的前驅稱為父事務,其它事務稱為子事務。事務的前驅稱為父事務,事務的下一層稱為子事務。
子事務既可以提交也可以回滾,但是它的提交操作並不馬上生效,除非由其父事務提交。因此就可以確定,任何子事務都在頂層事務提交後才真正的被提交了。同理,任意一個事務的回滾都會引起它的所有子事務一同回滾。
理論總結的再好,終歸都要通過實踐來進行理解。下面就來說說MySQL中是如何使用事務的。
在MySQL命令行的默認設置下,事務都是自動提交的,即執行SQL語句後就會馬上執行COMMIT操作。因此要顯示地開啟一個事務須使用命令BEGIN或START TRANSACTION,或者執行命令SET AUTOCOMMIT=0,用來禁止使用當前會話的自動提交。
來看看我們可以使用哪些事務控制語句。
有的時候有些SQL語句會產生一個隱式的提交操作,即執行完成這些語句後,會有一個隱式的COMMIT操作。有以下SQL語句,不用你去“管”:
以上的這些SQL操作都是隱式的提交操作,不需要手動顯式提交。
上面也說到了SET TRANSACTION用來設置事務的隔離級別。那事務的隔離級別是什麼東東?
在數據庫操作中,為了有效保證並發讀取數據的正確性,提出的事務隔離級別。
InnoDB存儲引擎提供事務的隔離級別有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。這些隔離級別之間的區別如下:
隔離級別
髒讀(Dirty Read)
不可重復讀(NonRepeatable Read)
幻讀(Phantom Read)
未提交讀(Read uncommitted)
可能
可能
可能
已提交讀(Read committed)
不可能
可能
可能
可重復讀(Repeatable read)
不可能
不可能
可能
可串行化(Serializable )
不可能
不可能
不可能
隔離級別越低,事務請求的鎖越少或保持鎖的時間就越短。InnoDB存儲引擎默認的支持隔離級別是REPEATABLE READ;在這種默認的事務隔離級別下已經能完全保證事務的隔離性要求,即達到SQL標准的SERIALIZABLE級別隔離。
我們可以可以用SET TRANSACTION語句改變單個會話或者所有新進連接的隔離級別。它的語法如下:
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
注意:默認的行為(不帶session和global)是為下一個(未開始)事務設置隔離級別。如果使用GLOBAL關鍵字,語句在全局對從那點開始創建的所有新連接(除了不存在的連接)設置默認事務級別。你需要SUPER權限來做這個。使用SESSION 關鍵字為將來在當前連接上執行的事務設置默認事務級別。 任何客戶端都能自由改變會話隔離級別(甚至在事務的中間),或者為下一個事務設置隔離級別。mysql> set session transaction isolation level repeatable read;Query OK, 0 rows affected (0.00 sec)
mysql> select @@tx_isolation;+-----------------+| @@tx_isolation |+-----------------+| REPEATABLE-READ |+-----------------+1 row in set (0.00 sec)
總結
這篇文章,基本上都是理論概念的堆積,實戰的東西基本沒有。但是,這些都不是問題,這也無法阻擋這篇文章成為一篇讀者喜歡的文章,是吧。好了,這篇關於MySQL中事務的文章就到此結束,以後如果有新的東西,就接著總結。