什么是事務?
事務就是將多個操作組合到一起完成,要么全部成功,要么全部失敗,具體到數(shù)據(jù)庫就是一組原子性的SQL查詢,事務內的語句要么全部成功,要么全部失敗。
轉賬的例子,小張給小王轉賬200塊,小張這邊要減200,小王那邊要加200,沒有事務的話如果小張減200成功,小王加200失敗,那么小張給小王說我明明轉賬給你了,你卻說沒搜到,然后兩個人就開始掐架了。有事務之后,小王那邊加兩百失敗,那么整個交易是不會成功的,小張的賬戶也不會少200。
MySQL中通過
START TRANSANTION
來開啟事務,通過
COMMIT
來提交事務。事務一旦提交成功,就說明事務內的一組操作全部執(zhí)行成功。
什么是ACID
ACID是一系列數(shù)據(jù)庫的設計模型,它強調業(yè)務數(shù)據(jù)的可靠性。MySQL 的InnoDB 存儲引擎就是使用ACID模型來實現(xiàn)的。所以當異常情況(比如軟件奔潰或者硬件出現(xiàn)故障)發(fā)生時并不會導致數(shù)據(jù)出現(xiàn)錯誤。使用ACID特性時,你不需要重新去造一個輪子來進行數(shù)據(jù)一致性檢驗和崩潰后數(shù)據(jù)恢復。但是當你有一定的軟硬件保障措施,并且可以容忍一定數(shù)據(jù)的丟失,那么可以改變MySQL ACID的設置來提高并發(fā)和吞吐量。
- A: atomicity. 原子性
一個事務必須被事務不可分割的最小工作單元,整個操作要么全部成功,要么全部失敗。MySQL通過COMMIT提交事務或發(fā)生異常情況時通過ROLLBACK語句來回滾事務。 - C: consistency. 一致性
數(shù)據(jù)庫總能從一個一致性的狀態(tài)轉換到寧一個一致性的狀態(tài)。比如轉賬的例子只要有任何一方發(fā)生異常就不會成功提交事務,事務所做的修改也不會持久化到數(shù)據(jù)庫中。 - I: isolation.隔離性
一個事務相對于寧一個事務是隔離的,而隔離的程度室友事務的隔離性決定。的。MySQL通過
SET ISOLATION LEVEL
來設置事務隔離級別。
- D: durability.持久性
一旦事務提交,就會永久的保存到數(shù)據(jù)庫中。
事務隔離級別
- READ UNCOMMITTED(未提交讀)
事務中的修改即使沒有提交,其他事務也能看見,事務可以讀到為提交的數(shù)據(jù)稱為臟讀。 - READ COMMITTED(提交讀)
一個事務開始后只能看見已經提交的事務所做的修改。也就是一個事務從開始到提交前所做的所有修改對其他事務都是不可見的。這個時候在事務中執(zhí)行兩次同樣的查詢可能得到不一樣的結果,所以也叫做不可重復讀。 - REPEATABLE READ(可重復讀)
是MySQL默認的隔離級別。解決了臟讀的問題,該級別保證了在同一個事務中多次讀取同樣記錄的結果是一樣的。理論上該級別存在幻讀的問題?;米x是指事務在讀取某個范圍的數(shù)據(jù)時,寧一個事務又在該范圍內中插入了新的數(shù)據(jù),當該事務再次讀取該范圍的數(shù)據(jù)時會讀到。InnoDB通過MVCC解決幻讀。 - SERIALIZABLE(串行化)
強制所有事務串行執(zhí)行,所以并發(fā)效率低。
一個金典搞笑的比喻: -
臟讀假如,中午去食堂打飯吃,看到一個座位被同學小Q占上了,就認為這個座位被占去了,就轉身去找其他的座位。不料,這個同學小Q起身走了。事實:該同學小Q只是臨時坐了一小下,并未“提交”。 -
不重復讀假如,中午去食堂打飯吃,看到一個座位是空的,便屁顛屁顛的去打飯,回來后卻發(fā)現(xiàn)這個座位卻被同學小Q占去了。 -
幻讀假如,中午去食堂打飯吃,看到一個座位是空的,便屁顛屁顛的去打飯,回來后,發(fā)現(xiàn)這些座位都還是空的(重復讀),竊喜。走到跟前剛準備坐下時,卻驚現(xiàn)一個恐龍妹,嚴重影響食欲。仿佛之前看到的空座位是“幻影”一樣。
參考文獻:
《高性能MySQL》
https://dev.mysql.com/doc/refman/5.7/en/mysql-acid.html
http://blog.sina.com.cn/jackbillow