面試官:說說數據庫事務吧

前言

上一篇說了如何查看MySQL的執行計劃,今天就來看一下數據庫的事務相關的知識點。程序員

面試官在數據庫這方面最常問的除了sql優化,還有數據庫事務、存儲引擎等相關知識。上期有人說沒有自動門,因此這一期我特意造了自動門,這門沒有四五塊造不下來。面試

注意:只是CRUD的搬磚工就不須要看了,看了也忘了,只須要拉到最後,點贊、在看、分享,一鍵三連而後收藏起來就好了。sql

什麼是事務

事務是指是程序中一系列嚴密的邏輯操做,並且全部操做必須所有成功完成,不然在每一個操做中所做的全部更改都會被撤消。數據庫

通俗點說就是要麼一塊兒活,要麼一塊兒死。併發

 

事務特性

事務特性就是普通都知道的ACID,那麼什麼是ACID,估計有些貨跟我以前同樣,只知道這個詞,不知道每一個字母表明的是什麼,此次就給翻譯翻譯什麼叫TMD驚喜(不,說錯了,是字母),我還特意下了一個有道詞典,浪費了幾十M的流量。高併發

 

A:Atomicity原子性優化

所謂原子性就是說事務是一個最小的單元,跟原子同樣不可再分割。一個事務中的全部操做要麼所有成功,要麼所有失敗,經過WAL(Write Ahead Log)實現。(HBASE也應用了這個技術)翻譯

I:Isolation隔離性3d

一個事務在操做還未結束以前,對其餘事務是不可見的,即一個事務內部的操做及使用的數據對其餘的併發事務是隔離的。鎖和多版本控制就符合隔離性。版本控制

相似與如今的共享文檔:我在編輯文檔未保存以前其餘人是不可見的。

D:Durability持久性

一旦事務提交,其所作的修改就會永久保存到數據庫中。

人也要學會持久,老子沒開車。好比健身,深蹲蹲一半怎麼行。

C:Consistency一致性

數據庫老是從一個一致性的狀態轉換到另一個一致性的狀態,也就是說在某個時間是A,另外一個時間是B。

全部事務對一個數據的讀取結果都是相同的,這是由原子性、隔離性、持久性共同保證的結果。

數據的完整性是經過其餘三個特性來保證的,包括原子性、隔離性、持久性,而這三個特性,又是經過 Redo/Undo 來保證的,爲了保證數據的完整性,提出來三個特性,這三個特性又是由同一個技術來實現的,因此理解 Redo/Undo 才能理解數據庫的本質。

 

隔離級別

READ UNCOMMITTED 未提交讀

事務所作的修改,即便未提交,對其餘事務也是可見的。事務能夠讀取未提交的數據,也稱爲髒讀。

也就是說能看見另外一我的正在編輯的內容是什麼,毫無隱私可言。

READ COMMITTED 提交讀,也稱不可重複讀

一個事務從開始直到提交以前,所做的修改對其餘事務是不可見的。也稱爲不可重複讀,由於執行屢次同樣的查詢,可能獲得不同的結果。

跟未提交讀正好相反,我只有保存了文檔,你才能看得見。

REPEATABLE READ 可重複讀

同一個事務中屢次讀取一樣的記錄的結果是同樣的。可能致使幻讀,在屢次讀取間隙中,可能有其它事務插入新的記錄,就會出現幻讀。

 

SERIALIZABLE 可串行化

最高隔離級別,強制事務串行執行,避免了幻讀的問題。

也就是事務必須一個一個排隊執行,沒有插隊的狀況。

併發事務問題

髒讀:

一個事務正在對一條記錄作修改,在這個事務完成並提交前,這條記錄的數據就處於不一致狀態;這時,另外一個事務也來讀取同一條記錄,若是不加控制,第二個事務讀取了這些「髒」數據,並據此作進一步的處理,就會產生未提交的數據依賴關係。這種現象被形象的叫做"髒讀"(Dirty Reads)。

所謂髒讀,就是說我沒提交別人都能看獲得事務,那麼後面我刪除掉編輯的內容的話他沒看,別人仍是覺得我編輯了內容。

不可重複讀

一個事務在讀取某些數據後的某個時間,再次讀取之前讀過的數據,卻發現其讀出的數據已經發生了改變、或某些記錄已經被刪除了!這種現象就叫做「 不可重複讀」(Non-Repeatable Reads)。

 

幻讀

一個事務按相同的查詢條件從新讀取之前檢索過的數據,卻發現其餘事務插入了知足其查詢條件的新數據,這種現象就稱爲「幻讀」(Phantom Reads)。

 

「注意」

不可重複讀和幻讀看起來很像,實際上是有差異的。

不可重複讀重點在於 UPDATA 和 DELETE,而幻讀的重點在於 INSERT

 

MVVC多版本控制

MVCC(Multi-Version Concurrency Control),行級鎖的一個變種,在不少狀況下避免了加鎖操做,開銷更低。

經過保存數據在某個時間點的快照來實現。便是無論執行多長時間,每一個事務看到的數據都是一致的。

根據事務開始時間不一樣,每一個事務對同一張表,同一時刻看到的數據多是不同的。

其實就是在高併發的訪問狀態下,對數據進行多版本控制,並經過事務的可見性來保證事務能看到本身應該看到的數據版本。

「那個多版本是如何生成的呢?」

每一次對數據庫的修改,都會在 Undo 日誌中記錄當前修改記錄的事務號及修改前數據狀態的存儲地址(即 ROLL_PTR),以便在必要的時候能夠回滾到老的數據版本。

InnoDB的MVCC,是經過在每行記錄後面保存兩個隱藏的列來實現的。兩列,一個保存了行的建立時間,一個保存了行的過時時間(或刪除時間),存儲的並非實際的時間值,而是系統版本號。每開始一個事務,系統版本號都會自動遞增。事務開始時刻的系統版本號會做爲事務的版本號,用來和查詢到的每行記錄的版本號進行比較。

MySQL 的 InnoDB 存儲引擎實現隔離級別的一種具體方式,用於實現「提交讀」和「可重複讀」這兩種隔離級別。而未提交讀隔離級別老是讀取最新的數據行,無需使用 MVCC。可串行化隔離級別須要對全部讀取的行都加鎖,單純使用 MVCC 沒法實現。

快照讀與當前讀

在 MVCC 併發控制中,讀操做能夠分爲兩類: 快照讀(Snapshot Read)與當前讀 (Current Read)。

「快照讀」:讀取的是記錄的可見版本(有多是歷史版本),不用加鎖。

「當前讀」:讀取的是記錄的最新版本,而且當前讀返回的記錄,都會加鎖,保證其餘事務不會再併發修改這條記錄。

注意:MVCC 只在 Read Commited 和 Repeatable Read 兩種隔離級別下工做。

「如何區分快照讀和當前讀呢?」

快照讀:簡單的 select 操做,屬於快照讀,不須要加鎖。

當前讀:特殊的讀操做,插入/更新/刪除操做,屬於當前讀,須要加鎖。

 

 

===============================

我是Liusy,一個喜歡健身的程序員。

獲取更多幹貨以及最新消息,請關注公衆號:上古僞神

若是對您有幫助,點個關注就是對我最大的支持!!!

相關文章
相關標籤/搜索