資料庫事務

2022-09-17 23:33:19 字數 3761 閱讀 3173

意味著我們對資料庫的一系列的操作,要麼都是成功,要麼都是失敗,不可能

出現部分成功或者部分失敗的情況。

思考:都成功很容易保證。在前面的操作已經成功了的情況下,後面的操作失敗了,怎麼保證全部

原子性,在 innodb 裡面是通過 undo log 來實現的。

undo log(撤銷日誌或回滾日誌)記錄了事務發生之前的資料狀態(不包括 select),在發生異常

執行undo 的時候,僅僅是將資料從邏輯上恢復至事務之前的狀態(回滾),而不是從物理頁面上操作實現的,屬於邏輯格式的日誌。

有了事務的定義以後,在資料庫裡面會有很多的事務同時去操作我們的同一張表或者同一行資料,必然會產生一些併發或者干擾的操作,對隔離性就是這些很多個的事務,對錶或者

行的併發操作,應該是透明的,互相不干擾的。通過這種方式,我們最終也是保證業務資料的一致性。

我們對資料庫的任意的操作,增刪改,只要事務提交成功,那麼結果就是永久性

的,不可能因為我們重啟了資料庫的伺服器,它又恢復到原來的狀態了。

指的是資料庫的完整性約束沒有被破壞,事務執行的前後都是合法的資料狀態。比如主鍵必須是唯一的,字段長度符合要求。另一方面是使用者自定義的完整性。

比如轉賬,a 賬戶餘額減少 1000,b 賬戶餘額只增加了 500,這個時候因為兩個操作都成功了,按

照我們對原子性的定義,它是滿足原子性的, 但是它沒有滿足一致性,因為它導致了會計科目的不平衡。還有一種情況,a 賬戶餘額為 0,如果這個時候轉賬成功了,a 賬戶的餘額會變成-1000,雖然它滿足了原子性的,但是我們知道,借記卡的餘額是不能夠小於 0 的,所以也違反了一致性。

原子性:當事務執行時,先記錄undolog,undolog記錄的是操作前的值,隨後記錄redolog,redolog記錄的是操作後的值,當未提交事務時發生宕機,先執行redolog,把值更新成操作後的值,最後執行undolog,把值更新回最初的值,從而保證事務的執行狀態一致。

隔離性:lbcc,在資料操作時有對應的鎖進行併發控制,髒讀由排它鎖,不可重複讀由共享鎖解決,幻讀由臨建鎖解決,因此保證事務的之間的隔離

永續性:資料修改時會寫入redolog,即使宕機資料也能從redolog中恢復修改的資料。實現了資料的持久化

一致性:上述三大特性最終保證了資料的一致性。

在乙個事務裡面,由於其他的時候修改了資料並且沒有提交(讀未提交),而導致了前後兩次讀取資料不一致的情況,這種事務併發的問題,我們把叫做髒讀

如果在轉賬的案例裡面,我們第乙個事務基於讀取到的第二個事務未提交的餘額進行了操作,但是第二個事務進行了回滾,這個時候就會導致資料庫不一致。乙個事務讀取到了其他事務已提交的資料導致前後兩次讀取資料不一致的情況(修改和刪除),叫做不可重複讀。

乙個事務前後兩次讀取資料資料不一致,是由於其他事務插入資料造(insert)成的,這種情況我們把它叫做幻讀

第一種,既然要保證前後兩次讀取資料一致,那麼我讀取資料的時候,鎖定我要操作的資料,不允許其他的事務修改就行了。這種方案我們叫做基於鎖的併發控制 lockbased concurrency control(lbcc)。如果僅僅是基於鎖來實現事務隔離,乙個事務讀取的時候不允許其他時候修改,那就意味著不支援併發的讀寫操作,會極大地影響運算元據的效率。

另一種解決方案,如果要讓乙個事務前後兩次讀取的資料保持一致,那麼我們可以在更新資料的時候建立乙個備份或者叫快照,後面再來讀取這個快照就行了。這種方案我們叫做多版本的併發控制 multi version concurrency(mvcc)

在 innodb 裡面,這兩種方案協同使用才能實現事務隔離級別。

mvcc 也是通過undo log實現的。

mvcc:只能查詢建立時間小於等於當前事務id的資料和刪除時間大於當前事務id的行(或未刪除)。在當前事務之後建立的資料,或者刪除資料,都不會影響當前事務的查詢操作。

myisam:支援表鎖

innodb:支援行鎖和表鎖

共享鎖:多個事務對於同一資料可以共享一把鎖,都能訪問到資料,但唯讀,不能修改。

排他鎖:寫鎖,x鎖,排他鎖不能與其他鎖並存,若乙個事務獲取了乙個資料行的排他鎖,其他事務不能在獲取該行的鎖。

意向共享鎖(is鎖):事務準備給資料強行加入共享鎖,說明乙個資料行加共享鎖前必須先取得該錶的is鎖

意向排他鎖(ix鎖):事務準備給資料行加入排他鎖,說明事務在乙個資料行加排他鎖前必須要先取得該錶的ix鎖

乙個事務要成功地鎖定一張表,前提:沒有其他任何事務已經鎖定了這張表的任意一行資料  此時如果沒有乙個意向鎖的話,此時需要進行全表掃瞄。

當有意向鎖之後,我們只需要檢視表上有沒有加鎖就行,類似於衛生間的們。會大大加快我們的查詢效率。

解決事務對資料併發訪問的問題。鎖的不是這一行資料,鎖的是innodb中的索引。一張表有沒有可能沒有索引?不可能的。如果 一張表沒有聚集索引,資料庫就會自動建立乙個預設的聚集索引,那麼我們加鎖的時候,由於是全表掃瞄,那麼就會把每一行的隱藏的索引鎖住,才會造成乙個鎖表的現象。

這些資料庫裡面存在的主鍵值,我們把它叫做 record,記錄,那麼這裡我們就有 4 個 record。根據主鍵,這些存在的 record 隔開的資料不存在的區間,我們把它叫做 gap,間隙,它是乙個左開右開的區間。假設我們有 n 個 record,那麼所有的資料會被劃分成多少個 gap 區間?答案是 n+1,就像我們把一條繩子砍 n 刀,它最後肯定是變成 n+1 段。最後乙個,間隙(gap)連同它左邊的記錄(record),我們把它叫做臨鍵的區間,它是乙個左開右閉的區間。

如果主鍵索引不是整型,是字元怎麼辦呢?字元可以排序嗎? 基於ascii 碼

第一種情況,當我們對於唯一性的索引(包括唯一索引和主鍵索引)使用等值查詢,精準匹配到一條記錄的時候,這個時候使用的就是記錄鎖。

比如 where id= 1 4 7 10

第二種情況,當我們查詢的記錄不存在,無論是用等值查詢還是範圍查詢的時候,它使用的都是間隙鎖。

舉個例子,where id >4 and id <7,where id=6。  gap 鎖只在 rr 事務隔離級別裡面存在。

第三種情況,當我們使用了範圍查詢,不僅僅命中了record 記錄,還包含了gap 間隙,在這種情況下我們使用的就是臨鍵鎖,它是 mysql 裡面預設的行鎖演算法,相當於記錄鎖加上間隙鎖

比如我們使用》5 <9 , 它包含了不存在的區間,也包含了乙個 record 7。鎖住最後乙個 key 的下乙個左開右閉的區間。

select  *  from t2 where id >5 and id <=7 for update; 鎖住(4,7]和(7,10]

select  *  from t2 where id >8 and id <=10 for update; 鎖住 (7,10],(10,+∞)

為什麼要鎖住下乙個左開右閉的區間?—— 就是為了解決幻讀的問題

innodb中的間隙鎖就是為了解決幻讀。

資料庫事務

事件是訪問並可能更新各種資料項的乙個程式執行單元。事件由事務開始與事務結束之間執行的全體操作組成。為了保證資料完整性,資料庫系統需要維護事務的以下性質 原子性 atomicity 事務中的操作要麼全部成功,要麼全部失敗。一致性 consistency 事務執行前後要保持資料庫的一致性。隔離性 iso...

資料庫 事務

資料庫事務 database transaction 是指作為單個邏輯工作單元執行的一系列操作。事務處理可以確保除非事務性單元內的所有操作都成功完成,否則不會永久更新面向資料的資源。通過將一組相關操作組合為乙個要麼全部成功要麼全部失敗的單元,可以簡化錯誤恢復並使應用程式更加可靠。乙個邏輯工作單元要成...

資料庫事務

這段時間面試,由於基礎不是特別好,遇到一些要筆試的公司。就會表示出來 今天有人問我,資料庫事務 是什麼。我只感覺十分熟悉。但是又說不出所以然。回來找了一下,現在整理記錄 1 定義 資料庫事務 database transaction 是指作為單個邏輯工作單元執行的一系列操作。事務處理可以確保除非事務...