上次我們在最後一部分,給出了乙個事務操作的模型和內部簡單實現的方式,以期讓大家能針對事務有乙個比較簡單的印象。
今天,我就嘗試針對事務的基本特性做乙個簡單的概述。 當然,因為仍然是概述,所以不會特別深入的去介紹和分析內部的機制,只希望能夠將一些難以理解的概念,用舉例子的方式協助大家能夠更容易的理解事務的基本概念。
談到事務,我們要做的第一件事,就是理解,什麼叫做事務,以及為什麼要有事務。
事務這個概念的產生,仍然是為了解決我們在之前提到的打字機問題 :
( 像我們在上文中提到的,計算機只是乙個圖靈機,所以,如果計算機要實現我們現實的世界的一些操作模式,只能靠模擬的方式進行。上次我們是使用鎖來處理一次寫請求過程裡面對應的多次計算機操作的時候怎麼看起來像是一次整體的操作。 而在這裡我們要解決的問題是,一組使用者的多次寫入和讀取操作,怎麼能夠被看起來像是一次整體的操作呢?
首先,讓我用個例子來看看為什麼需要這樣做。
為了後面敘述方便,讓我們先設定乙個實際的環境場景:
梅梅給李雷打了乙個**,說最近想買一本英語書,需要一百元,李雷得知梅梅的請求,二話不說就開始操作他的網銀給梅梅做了轉賬付款:
假定李雷賬戶是pk=1 , 韓梅梅的賬戶是pk=2
begin transaction;
select cash from t where pk = 1; a操作
update t set cash = cach-100 where pk = 1; b操作
update t set cach = cash+100 where pk =2; c操作
commit;
好,我想我針對事務場景的場景應該描述清楚了。
首先我們來介紹原子性
從業務需求來說,我們必須保證,只要李雷的賬戶減少了100塊,那麼這一百塊必須能夠加到韓梅梅的賬戶裡。如果中間有任何乙個操作失敗,系統不能夠憑空多出一百元(李雷沒有減錢,韓梅梅卻加了錢) , 也不能憑空少了一百元(李雷減少了一百元,韓梅梅賬戶卻沒增加)。
為了做到這個特性,就必須保證李雷賬戶減錢與韓梅梅賬戶加錢這兩件事,要麼同時成功,要麼同時不成功。
這就是事務中的第乙個重要的概念:原子性的含義
下面我們來介紹一致性
當看到自己的賬戶減少了一百塊以後,李雷問**那頭的梅梅:「梅梅,我看我這裡操作成功了,你那裡收到錢了沒?」 。 如果這時候梅梅跟李雷說:"雷~ 我沒看見我賬戶的錢有變化啊「。
想一想,這時候李雷會是什麼感覺? 他的心裡一定會」咯噔「一下, 錢不會是丟了吧? 趕緊給支付寶打**確認怎麼回事!
這裡的這種情況,就是一致性沒***而可能出現的一種情況,簡單來說,就是其他使用者看到了事務三步操作過程中的中間狀態資訊,這種資訊是明顯反使用者常識的,所以應該盡可能被避免。
因此我做個簡單小結,這裡我們需要能夠保證,當李雷看到自己賬戶減少了100元的時候,韓梅梅的賬戶裡也必須能夠看到增加了一百元。
這種要麼同時出現,要麼同時消失的保證,就是事務一致性。
在看到這裡的時候,相信一定會有人來問,這個一致性和原子性,看起來都是要麼成功,要麼不成功的感覺,那麼這兩個概念有什麼差異呢?
恩,下面我就來嘗試解決這個疑惑吧~
區分這倆概念的關鍵,其實在乙個"看"字,一致性約束的是乙個使用者寫入並提交資料之後,其他使用者去去讀這條記錄的時候,要麼看到的是李雷還沒有給韓梅梅轉賬的那個狀態,要麼就是李雷已經成功轉賬給了韓梅梅的狀態,而在這兩個狀態之間的事務狀態,比如李雷減少了100元,但韓梅梅還沒加上這一百塊的這個中間狀態則不能夠被其他人看到。而原子性只需要保證操作要麼」最終「全部成功,要麼」最終「全部失敗而已。原子性不約束可見性,只保證操作的邏輯性。
這,就是一致性和原子性保證的差別。
最後,我們來介紹永續性
我想,任何使用者都一定不希望下述的這種情況發生:李雷和韓梅梅都已經確認這次轉賬成功了。然而過了5分鐘,韓梅梅想用這充滿了感情的100元去買他想要的英語書的時候,卻發現錢不翼而飛了!? 於是趕緊給支付寶打**詢問,支付寶卻回答說: 對不起您那賬戶的資料庫伺服器重啟了,丟失了一部分的資料,您賬戶裡的那個錢正好在丟失範圍內,請節哀。
我想這時候應該有(bi....)的動機了吧:)
於是,這裡就需要做乙個很基礎的保證:如果乙個事務結束後,已經被其他人看到了,那麼就不能夠回退到事務之前的狀態了。
這就是事務的第三個重要的概念:永續性的含義
好了,我們介紹了三個關鍵的概念,原子性a,一致性c,永續性d。 下課~
可能有看過其他資料庫書籍的人會問了:」等等,你這不對吧?事務不是四個特性麼?別忽悠我們啊,我們明天面試還得背這些概念呢,要不找不到工作啊~」
好好好,我馬上來介紹隔離性。。。
其實,我將隔離性從上面幾個屬性中剝離出來,是有我自己的考慮的,主要原因是我個人認為,隔離性從邏輯概念上不與上面介紹的acd平級。為什麼這麼說呢?我的理由是,如果要模擬現實中發生的各種操作,只需要保證acd三個屬性,就能夠完美的完成一次事務操作了,隔離性則明顯是多餘的。。
」那麼,既然多餘,去掉不就好了。。還留著他幹啥?不知道這個隔離性是最(biiiii...)複雜的概念麼,上次面試就因為沒說明白這貨所以面試被鄙視了呢!」
唉,這還真去不掉,因為去掉了,資料庫的事務就慢的受不了了。。所以資料庫開山的那批大牛也就不顧邏輯的清晰不清晰了,把這個概念加入了事務的四大要素。
從這件事,我們也就能感受到這個概念對效能的重要性了吧。。甚至可以說,資料庫事務效能是否能夠提公升,關鍵就看你能接受哪個隔離級別了呢!
咋樣?是不是對這個概念肅然起敬了?好,那麼我們就來看看隔離性是個什麼東西。
首先,明確隔離性要解決的問題域,與上面為了保證一次事務提交邏輯上的正確性不同的,隔離性主要解決的問題是效能,或者更直接點,就是盡可能的降低受到鎖影響的事務程序的個數的。
然後,看他解決問題的方法:
在之前我們提到,一致性要保證資料被其他人看到的時候必須是乙個完整的資料狀態,資料更新過程中的中間狀態則不能被看到。
好了,大牛們剛剛說了限定條件,下面立馬給自己來了個響亮的自抽。。
隔離性的最低級別,就是讀未提交
什麼叫讀未提交呢? 我們來抄維基。。
讀未提交,可能出現髒讀,當乙個事務試圖讀取另乙個還未提交的事務正在修改的某一行資料時,骯髒讀取(dirty reads)就會發生。
簡單來說,就是乙個事務,需要同時更新兩張表的資料,而另乙個人去讀這兩張表的資料的時候,可能能夠讀到一張表的新值和另外一張表的老值!
這明顯就違反了一致性不是 :)
其實,從我上面舉出的例子,你就能感受到,一致性和隔離性應該被一起考慮,一致性描述的是理想的事務過程應該怎樣,而理想的事務因為鎖的範圍太大以至於效能難以接受,所以就使用隔離性的多個隔離級別來破壞一致性應該給出的保證,以換取更小的鎖範圍,從而獲取更高的效能。
在這一篇,我不會擴充套件隔離性這個概念,因為如果不聯絡實際的資料庫實現而死記硬背各種隔離級別的概念,我覺得太難理解這個概念了。
因此,我將在後面展開討論事務和分布式事務的章節再來關注隔離性的四個級別的問題。在這裡,如果你回顧本篇的時候,如果能回想起原子,一致,持久這三個特性產生的原因,然後又能理解到隔離性主要解決的問題域,以及從最低級別:讀未提交,到最高端別:可序列化,隔離性的本質就是乙個鎖的範圍逐漸擴大,效能逐漸降低,但能提供更強級別的一致性保證的這麼乙個特徵。 那麼我的目標也就達到了 。
隨著隔離性概要介紹的完結,資料庫系統概述這一章也就隨著這篇概述的結束而結束了,在本章,我寫作的主要目標就是,用盡可能具象化的例子來對乙個資料庫系統做了乙個概要性的描述。
下面,我會在後面的章節開始深入到分布式儲存的一些重要的領域進行更深入的**。
enjoy~
李雷和韓梅梅的老師怎麼樣了?
hello my name is li lei.what s your name?hello my name is han meimei.how are you,miss gao?你們的miss gao還好嗎?那些年,miss gao們 高老師 都說過 你們是我教過最差的一屆學生!現在回憶起來,笑著...
一次完整的HTTP事務
http通訊機制是在一次完整的http通訊過程中,web瀏覽器與web伺服器之間將完成下列7個步驟 1.建立tcp連線 在http工作開始之前,web瀏覽器首先要通過網路與web伺服器建立連線,該連線是通過tcp來完成的,該協議與ip協議共同構建internet,即著名的tcp ip協議族,因此in...
巢狀事務的一次實踐
最近在乙個專案中,需要實現自動對賬功能,收銀機會定時對比本地和遠端的訂單,遠端發現缺少的,會自動補全。所謂補全,就是批量插入缺失的訂單。基於這個場景,就存在乙個細節的問題,因為插入訂單涉及兩個表,如果某些情況下,乙個表插入失敗,訂單插入事務需要回滾。但是不能回滾之前插入的訂單資料,顯然這裡就設計子事...