数据库之 事务
什么是事務,一個事務是一個只包含所有讀/寫操作成功的集合。通常可以認為 事務包含了多個 寫操作 sql 。
事務的四個特點
一個事務本質上有四個特點,也就是ACID:
- Atomicity原子性,事務中所有的操作要么全部成功,要么全部失敗。 這個容易理解。
- Consistency一致性,事務結束后系統狀態是一致的;
- Isolation隔離性,并發執行的事務彼此要 進行讀寫隔離(具體如何隔離, 按情況而定);其實這是個不確定狀態。應該具體到四個層次中進行討論。
- Durability持久性,事務完成后所做的改動都會被持久化,即使發生災難性的失敗。通過日志和同步備份可以在故障發生后重建數據。也就是被固化。這個容易理解。
?
這里的一致性,有點不好理解。 其實可以這么理解:
一致性是指事務必須使數據庫從一個一致性狀態 變換到 另一個一致性狀態,也就是說一個事務執行之前和執行之后都必須處于一致性狀態。
拿轉賬來說,假設用戶A和用戶B兩者的錢加起來一共是5000,那么不管A和B之間如何轉賬,轉幾次賬,事務結束后兩個用戶的錢相加起來應該還得是5000,這就是事務的一致性。 ?
重點說說 隔離性
隔離性,雖然按我理解是 一種 不是特性的特性,更像是特點, 但普遍認為它是一種 重要數據庫特性, 那就這樣認為吧。它當然是很重要的,它內涵十分豐富的。
它其實就是說隔離級別。數據庫事務的隔離級別有4個,由低到高依次為Read uncommitted?、Read committed?、Repeatable read?、Serializable?,這四個級別可以逐個解決臟讀?、不可重復讀?、幻讀?這幾類問題。 友好度:? 序列化讀 > 可重復讀 > 提交讀 > 未提交讀 > 不支持:
| ? | 臟讀 | 不可重復讀 | 幻讀 |
| Read uncommitted | √ | √ | √ |
| Read committed | × | √ | √ |
| Repeatable read | × | × | √ |
| Serializable | × | × | × |
注意:我們討論隔離級別的場景,主要是在多個事務并發?的情況下。
JDK 的API :
?大多數數據庫的默認級別就是Read committed,比如Sql Server , Oracle。?Mysql的默認隔離級別就是Repeatable read。
?
再論 臟讀、幻讀、不可重復讀
1.臟讀(Phantom Read): 臟讀就是指當一個事務正在訪問數據,并且對數據進行了修改,而這種修改還沒有提交到數據庫中,這時,另外一個事務也訪問這個數據,然后使用了這個數據。2.不可重復讀(Unrepeatable Read): 是指在一個事務內,多次讀同一數據。在這個事務還沒有結束時,另外一個事務也訪問該同一數據。那么,在第一個事務中的兩次讀數據之間,由于第二個事務的修改,那么第一個事務兩次讀到的的數據可能是不一樣的。這樣就發生了在一個事務內兩次讀到的數據是不一樣的,因此稱為是不可重復讀。(即不能讀到相同的數據內容) 例如,一個編輯人員兩次讀取同一文檔,但在兩次讀取之間,作者重寫了該文檔。當編輯人員第二次讀取文檔時,文檔已更改。原始讀取不可重復。如果只有在作者全部完成編寫后編輯人員才可以讀取文檔,則可以避免該問題。3.幻讀(Dirty Read): 是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的全部數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那么,以后就會發生操作第一個事務的用戶發現表中還有沒有修改的數據行,就好象 發生了幻覺一樣。 例如,一個編輯人員更改作者提交的文檔,但當生產部門將其更改內容合并到該文檔的主復本時,發現作者已將未編輯的新材料添加到該文檔中。如果在編輯人員和生產部門完成對原始文檔的處理之前,任何人都不能將新材料添加到文檔中,則可以避免該問題。 出至于 https://blog.csdn.net/JIESA/article/details/51317164
?
臟讀容易理解,但是?不可重復讀 有些奇怪。事務t1 兩次讀數據d1, 為什么會不一樣,因為其他的事務(比如t2)在兩次讀操作之間修改了 d1,那么,為什么t2 可以修改d1,d1 不是處于事務之中嗎? 事務之中的資源不是應該被上鎖嗎? 其他的事務為什么可以訪問? 需要說明的是,雖然我們一般認為事務就會給資源加鎖,防止任何其他線程的訪問,但是, 我們需要明白事務并不一定意味著加鎖,加鎖確實是一種行為,但是事務依據隔離級別而定,還有各種 行為呢, 比如 臟讀、未提交讀。? —— 另外,鎖可以防止其他線程的訪問,但是沒說是防止讀還是防止寫, 如果僅僅是防止讀, 那么其他線程的事務 有可能在 當前事務的 兩次讀 之間 進行讀的?。。。
?
臟讀、不可重復讀讀 是 難以被接受的, 因為會出現一些混亂,以及難以理解的情況。
(注意, 未提交讀本身不是個問題,它只是個隔離級別。它確實會引起一些的問題)
幻讀 更加的難以理解。不可重復讀和幻讀很相近。一定需要注意的是,不可重復讀強調的是記錄的更新(update),幻讀強調的是插入和刪除(insesrt和delete)
?
如何實現的?
要理解 事務的隔離級別,我們需要大概知道 它是如何實現的,以MySQL為例。 我大膽猜測一下。
臟讀,就是說,t1未提交,t2 就可以讀到t1的修改了。 可以想象,如果t1、t2操作的數據 是共享的,那么即使 未提交,卻相互可見,那么就出現了 臟讀。從鎖的角度來看, 可以認為 臟讀是 根本沒有加鎖的 結果。
?
不可重復讀,就是說,假設依次發生 t1開始,xxx,t1 讀操作r1,t2更新操作w1,t1讀操作r2,xxx, t1 提交,那么r2,讀到的是 w1的結果。可以想象,如果r1 的讀操作沒有排斥 w1的寫操作的話,那么就會出現這個問題。就是說,讀操作r1 應該在讀的那一刻,鎖住數據,不讓其他線程的事務進行 寫,但允許他們讀。 這個可能是沒有加獨占鎖的結果, 比如只是加了個共享鎖, 然而并沒有什么卵用。
我們通過對r1 增加 獨占鎖,可以解決這個問題。 另外, 我們要區分 是讀整個表呢? 還是某一行, 或是某幾行呢?? 如果是 讀某一行, 我們當然也可以 對整個表啟用 獨占鎖, 但是這樣的話,成本有點高,性能有所下降, 這個時候我們可以啟用 行的 獨占鎖 ; 如果是讀整個表呢? 那當然需要? 對整個表啟用 獨占鎖; 如果是某個范圍呢? 我們需要 范圍鎖(有這個鎖嗎?)。
?
幻讀,就是說,依然假設依次發生 t1.r1,t2.w1, t1.r2, 假設r1 是讀整個表 或者某部分的 部分( 不是 按唯一id 查詢),假設我們已經 對r1 啟用的 整表獨占鎖 或者該鎖住的 部分。 按理來說,r2 應該會排斥w1 才對,也就是說,按理來說,r2 應該發生在w1 之前,但是呢。?整表獨占鎖 也可以細分為 很多的情況, 比如我們可以鎖住整個所有的數據(或者整個索引文件), 這樣這些數據是不能夠修改的,那么就不會出現幻讀。 如果 這個時候 表新增一行或刪除了其他行的數據? 那么, 假設?整表獨占鎖 允許新增,也就是沒有鎖住新增的,或者允許刪除,那么就出現了 一個事務內 兩次相同的 讀操作, 讀到不同的 結果了, 也就是出現了幻讀了!!
?
特別說明,我認為r1 應該是r2是 同一個sql, 也就是開始r1是 讀表操作, 后面的r2也是讀表操作。而不是說 r1 讀行, r2 讀表,如果是這樣,會出現更多的問題, 但我認為這個是另外的話題了。我認為 幻讀 應該的是?r1,r2 讀表 引起的,而不是 按id 讀行。
所謂 讀表操作 sql ,可能是 沒有where 條件的查詢, 也可以是 有條件的sql, 總之不是 根據 唯一索引查詢 的 sql。
知其所以然
通過上面的表,我們知道了各個隔離級別 可以引起的問題。
?Read uncommitted 可以引起臟讀,不可重復讀,幻讀,why,因為 它可能 根本沒有加鎖,t1的寫,沒有對t2的讀隔離,所有,那么t1的寫 對 t2是立即可見的, 臟讀都防止不了,其他各種問題 更加防止不了。
Read committed 可以引起不可重復讀,幻讀, 這個可能是沒有加獨占鎖,那么 t1 還是不能限制t2 的寫,自然會引起?不可重復讀, 幻讀就更加不要說了。
Repeatable read?可以引起幻讀,?這個可能是沒有 “真正的獨占的”? “鎖住整個表或者該鎖住的 部分”, 雖然表的已經存在的 數據是 鎖住了,但是新增的呢? 刪除的呢?
?
前面假設t1、t2 使用的相同的隔離級別, 如果他們不同,那么情況可能更加復雜。(同一個時間,t1、t2 使用的不同的隔離級別嗎? 存疑)
?
ACID與CAP、BASE
ACID是傳統數據庫常用的設計理念,追求強一致性模型。BASE支持的是大型分布式系統,提出通過犧牲強一致性獲得高可用性。
ACID和BASE代表了兩種截然相反的設計哲學
在分布式系統設計的場景中,系統組件對一致性要求是不同的,因此ACID和BASE又會結合使用。
?
BASE的BA 基本可用是指分布式系統在出現不可預知故障的時候,允許損失部分可用性----注意,這絕不等價于系統不可用。比如:
(1)響應時間上的損失。正常情況下,一個在線搜索引擎需要在0.5秒之內返回給用戶相應的查詢結果,但由于出現故障,查詢結果的響應時間增加了1~2秒
(2)系統功能上的損失:正常情況下,在一個電子商務網站上進行購物的時候,消費者幾乎能夠順利完成每一筆訂單,但是在一些節日大促購物高峰的時候,由于消費者的購物行為激增,為了保護購物系統的穩定性,部分消費者可能會被引導到一個降級頁面
BASE的S 是說, 分布式系統多個節點,只保證部分而不是 全部 節點 擁有 最新的數據備份, 是一個中間狀態。并認為該中間狀態的存在不會影響系統的整體可用性,即允許系統在不同節點的數據副本之間進行數據同步的過程存在延時。
BASE的E 是說,分布式系統的所有節點,經過一些延時之后, 最終都擁有了 最新的數據備份。
?
ACID和BASE 這兩個術語都好記有余而精確不足,出現較晚的BASE硬湊的感覺更明顯,它是“Basically Available, Softstate, Eventually consistent(基本可用、軟狀態、最終一致性)”的首字母縮寫。其中的軟狀態和最終一致性這兩種技巧擅于對付存在分區的場合,并因此提高了可用性。
CAP與ACID的關系更復雜一些,也因此引起更多誤解。其中一個原因是ACID的C和A字母所代表的概念 完全不同于CAP的C和A。還有一個原因是選擇可用性只部分地影響ACID約束。
總的來說,BASE理論面向的是大型高可用可擴展的分布式系統,和傳統的事物ACID特性是相反的,它完全不同于ACID的強一致性模型,而是通過犧牲強一致性來獲得可用性,并允許數據在一段時間內是不一致的,但最終達到一致狀態。但同時,在實際的分布式場景中,不同業務單元和組件對數據一致性的要求是不同的,因此在具體的分布式系統架構設計過程中,ACID特性和BASE理論往往又會結合在一起。
ACID 是面向單機的事務特性,如果mysql 數據庫做了集群呢?ACID? 是根本沒有考慮網絡問題的,而一旦涉及集群或者分布式系統,那么,P相關問題不可避免,那么我們可能需要結合?ACID ,CAP,甚至BASE。
?
當我們把事務的ACID 特性和 分布式理論的CAP 統一起來的時候,其實就是 所謂的 分布式事務 !!!
?
參考:
https://blog.csdn.net/JIESA/article/details/51317164https://www.jianshu.com/p/f432665d523f https://blog.csdn.net/zh521zh/article/details/69400053
https://blog.csdn.net/wireless_com/article/details/79153643? posted on 2018-12-14 20:23 CanntBelieve 閱讀(...) 評論(...) 編輯 收藏
轉載于:https://www.cnblogs.com/FlyAway2013/p/10120854.html
總結
- 上一篇: 【js操作url参数】获取指定url参数
- 下一篇: 法国和瑞士哪个地方买天梭表便宜,国内60