深入理解事務和MVCC

文章目錄

  • 事務
    • 定義
    • 并發事務
    • 代碼實現
  • MVCC
    • 定義
    • 核心機制

事務

定義

什么是事務? 事務是指一組操作要么全部成功,要么全部失敗的執行單位。
在數據庫中,一個事務通常包含一組SQL語句,系統保證這些語句作為一個整體執行。

為什么引入? 想象一下,若沒有事務銀行中的轉賬操作可能會發生:A對B轉賬,A這邊已扣款但B卻沒收到。這不是虧麻了。再比如,多個線程同時操作一條數據,那么這條數據該聽誰的呢?引入事務就是為了解決這些問題,保證數據的完整性,一致性和可靠性。

特性: 有四大特性:

特性全稱含義
AAtomicity(原子性)操作不可分割,要么全成功,要么全失敗
CConsistency(一致性)執行完事務后,數據要從一個一致狀態轉到另一個一致狀態
IIsolation(隔離性)并發事務之間互不干擾
DDurability(持久性)提交后的數據必須永久保存,即使系統宕機

并發事務

并發事務常見的問題: 了解事務的基本原理后,我們在數據庫執行多個事務時,實際上是并發執行。但就像線程并發執行,又會引起很多問題。主要歸為以下三類:
(1)臟讀:指事務1在訪問數據A時,事務2在修改數據A,此時事務1拿到的數據不是最終數據。
如何解決?只需要在事務1中寫的過程加鎖(可以理解為多線程編程的鎖),也就是寫的過程不會受到任何外部的干擾。任何事務讀到的肯定是寫完之后的數據了。

(2)不可重復讀:雖然在寫的過程加鎖可以解決臟讀問題,但是沒說讀的時候不能寫啊? 假設事務1讀數據A時,事務2在寫數據A,事務1讀到一半的時候,事務2寫完了。此時事務1假設繼續讀下去,發現內容與前文不一致了。這就是不可重復讀。
如何解決?顯而易見,給讀的過程也加鎖。這樣讀寫都不被干預,那么這就不管怎樣都安全了嗎?

(3)幻讀:顯然還是不安全,我們考慮一種情況,事務1,2在數據庫中讀寫都加鎖了。事務1讀取數據A,事務2讀取數據A,在事務2讀取A時,事務1不能讀取A,但它可以操縱數據庫的其他的數據。假設事務1新增數據B,事務2在讀完數據A后,再查詢數據庫有多少條數據。發現多了一條,這就是“不敢睜開眼,希望是我的幻覺”(歌詞哈哈),大家理解記憶這就是幻讀!(當然我理解的可能也有偏差,不過大多數文章都以新增數據舉例)。
如何解決?直接徹底串行化,事務2干活的同時,事務1徹底不許做別的了。

問題描述舉例
臟讀(Dirty Read)一個事務讀到另一個事務尚未提交的數據T1更新數據,T2讀取了這個數據,后來T1回滾,T2讀到的是無效數據
不可重復讀(Non-repeatable Read)同一事務中多次讀取結果不一致T1兩次讀取某條記錄,中間T2修改了這條記錄
幻讀(Phantom Read)同一事務中兩次查詢數據條數不一致T1讀取符合條件的所有記錄,T2新增了一條符合條件的數據,T1再次讀取發現“多出一條”
隔離級別描述會不會出現臟讀不可重復讀幻讀
READ UNCOMMITTED最低,不加鎖? 有? 有? 有
READ COMMITTED讀已提交(Oracle 默認)? 無? 有? 有
REPEATABLE READ可重復讀(MySQL 默認)? 無? 無? 有(InnoDB 用間隙鎖避免)
SERIALIZABLE串行化,最高隔離? 無? 無? 無

代碼實現

不做重點,感興趣的可以直接在項目中練習

Connection conn = null;
try {conn = dataSource.getConnection();conn.setAutoCommit(false); // 開啟事務// 執行多個 SQL 語句updateAccount1(conn);updateAccount2(conn);conn.commit(); // 提交事務
} catch (Exception e) {if (conn != null) conn.rollback(); // 回滾事務
} finally {if (conn != null) conn.close(); // 關閉連接
}

MVCC

定義

介紹完事務后,我們可以介紹一種更輕量化的解決事務并發問題的方法。講之前簡單講一下,事務是怎么實現全不做的? 可能會有疑問,事務執行了多個操作,還差幾個操作就執行完了,這個時候突發緊急情況不能做了,怎么把之前的操作取消呢。實際上可以理解為數據庫已經將之前的版本的數據記錄下來,將之前操作所修改的數據全部還原。這就是回滾。

??什么是MVCC? MVCC -多版本并發控制,它允許事務在不加鎖的情況下并發讀寫,通過維護數據的多個版本實現。神奇吧,竟然不用加鎖也可以實現。那么它是怎樣版本控制的呢?

為什么引入? 講原理之前,先要了解之前加鎖方案存在的缺陷以及MVCC的目的
加鎖方案主要有以下兩個問題

傳統機制問題
讀加共享鎖,寫加排他鎖讀寫互相阻塞,效率低下
高并發下,鎖沖突頻繁會造成 鎖等待、死鎖、性能瓶頸

MVCC目的:
在 無需加鎖的前提下,實現“讀寫分離”、高并發讀操作的一致性。也就是避免鎖的使用

核心機制

原理
(1)在InnoDB中,MVCC維護每一行的數據多個版本來實現。主要依靠兩個字段和undo log機制。

(2)兩個字段是指數據庫為每條記錄隱藏的維護了兩個字段分別是更新此記錄的事務id和回滾指針。

字段含義
trx_id插入或最后修改該行的事務ID
roll_pointer指向 undo log 中上一個版本的地址,形成版本鏈

每個事務啟動時,系統會分配一個全局遞增的事務ID。

(3)undo log
undo log 大家可理解為舊賬本,就像夫妻倆一旦吵架就要翻舊賬。事務也是如此發生沖突,直接翻舊賬。 具體為當一個事務更新記錄時,數據庫首先將未更新的記錄先保存到undo log中,然后事務才可以更新記錄,并將記錄中的roll_pointer 指向此舊帳本對應的記錄。

[當前版本]trx_id: 15roll_pointer --> undo log #1[undo log #1]trx_id: 12roll_pointer --> undo log #2[undo log #2]trx_id: 9

(4)那如何通過翻舊賬實現可見性呢?
這里要注意,我們在這通常針對的讀操作不加鎖,寫操作數據庫一般默認都會加鎖,我們盡可能減少的是讀操作的加鎖。假設有一組并發的事務開始執行時,系統依次給每個事務分配遞增ID。 其中當這里邊的事務讀取記錄時,核心內容就一條即更新這條記錄的事務id必須小于這一組事務id的最小值。讀取時這條記錄才會對事務可見。或者修改這一條記錄事務id是它本身,這種情況也是可見的。其他條件,比如大于這一組事務id的最小值,說明更新這條記錄的事務id在這一組事務中,由于是并發執行,所以對其不可見。此時,記錄的回滾指針會指向之前的版本記錄讓其事務讀取。如下:

判斷條件是否可見原因
trx_id == 當前事務ID當前事務自己創建或修改的記錄
trx_id < 最小活躍事務ID創建該記錄的事務已在當前事務啟動前提交
trx_id ∈ 活躍事務列表創建該記錄的事務尚未提交
否則否,繼續通過 roll_pointer 回滾舊版本找到對當前事務可見的歷史版本

這里解釋一下可能存在的疑問。 事務出現不會直接獲取要讀取記錄的事務id字段。而是當我們在事務中查詢語句執行時,才會獲取更新此記錄的事務ID。這種方式也叫快照讀,就是說讀取的時候會給記錄拍照定格ReadView。不是事務出現拍照定格。
事務T1如果還沒進行讀取,是不會生成Read View的。當它真的去執行 SELECT 操作時,它才會拍下“當前全局事務表中的活躍事務ID快照所以 Read View 中的最大事務ID(up_limit_id)可能遠遠大于當前事務自己的ID

當前活躍的事務創建的 Read View 都是相同的嗎?Read View 是每個事務“第一次執行快照讀”時才生成的。即便兩個事務同時處于“活躍”狀態,它們的 Read View 也可能在不同的時刻拍下,因此內容可能不同。快照讀和其他操作的區別:

操作類型讀寫類型是否生成 Read View能否看到未提交數據是否加鎖
SELECT快照讀(Snapshot Read)? 是(第一次讀時生成)? 否(只能看到歷史版本)? 否
SELECT ... FOR UPDATE / SELECT ... LOCK IN SHARE MODE當前讀(Current Read)? 否? 是(讀取最新已提交或當前數據)? 是(加行鎖)
UPDATE / DELETE當前讀 + 寫操作? 否? 是(讀取最新數據)? 是(加排他鎖)
INSERT寫操作? 否-(新數據,無歷史版本)? 是(加插入意向鎖)

總結來說,本文面向面試對其基本原理做了一定梳理,希望可以幫助大家通過面試。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88890.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88890.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88890.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用 Python 繪制精美雷達圖:多維度材料屬性對比可視化全指南

&#x1f31f; 為什么選擇雷達圖&#xff1f;從材料科學到多維數據對比的可視化利器 在科研和數據分析領域&#xff0c;當我們需要同時展示多個維度的數據對比時&#xff0c;傳統的柱狀圖或折線圖往往顯得力不從心。這時候&#xff0c;雷達圖&#xff08;Radar Chart&#xff…

Excel學習03

超級表與圖表 Excel中具有超級表的功能。所謂超級表&#xff08;官方名稱為“表格”&#xff0c;快捷鍵CtrlT&#xff09;是Excel中一個強大的數據管理工具&#xff0c;它將普通的數據區域轉換為具有只能功能的交互式表格。 這就是表格變為超級表的樣子。超級表默認具備凍結窗…

Netflix 網飛的架構演進過程、Java在網飛中的應用|圖解

寫在前面 上一篇文章中&#xff0c;我們講解了網飛當前的架構&#xff0c;但網飛的架構并不是一開始就是這樣的&#xff0c;而是不斷演進發展才是當前的樣子。 這篇文章我們就來講講網飛架構的演進過程。 第一階段&#xff1a;Zuul Gateway REST API 使用 Zuul 作為API網關…

使用ros2服務實現人臉檢測2-人臉檢測功能實現(適合0基礎小白)

文章目錄 一、用到的庫二、使用步驟1.引入庫2.獲取圖片真實路徑3.檢測人臉4.繪制人臉5.顯示結果6.更改setup.py7.完整代碼 三、結果展示 一、用到的庫 face_recognition&#xff1a;實現在圖片中檢測人臉。 cv2&#xff1a;顯示圖片&#xff0c;并且可以在圖像中展示檢測結果。…

中國農村統計年鑒-Excel版(1985-2024年)

《中國農村統計年鑒》系統收錄了全國和各省農村社會經濟統計數據&#xff0c;以及近年全國農村主要統計數據&#xff0c;是一部全面反映我國農村社會經濟情況的資料性年刊。年鑒內容覆蓋農村人口結構、農業產值、主要農產品產量、市場物價、進出口貿易以及收入消費水平等社會經…

golang pprof性能調試工具

簡介 pprof是性能調試工具,可以生成類似火焰圖、堆棧圖,內存分析圖等。 整個分析的過程分為兩步:1. 導出數據,2. 分析數據。

PPIO × 302.AI:三分鐘搭建可共享的聊天機器人

最近&#xff0c;各主流模型廠商頻頻發布新模型&#xff0c;有一如既往強大的DeepSeek-R1-0528&#xff0c;擅長長輸入推理的MiniMax-M1-80k…… 好用的AI大模型這么多&#xff0c;如何才能集成在一個應用自由使用呢&#xff1f;302.AI作為企業級AI應用平臺支持各主流模型調用&…

怎么樣在自己的網站/獨立站中添加視頻?

文章目錄 **前言** 一、視頻在網站/獨立站的好處二、視頻嵌入網站的原理三、如何簡易地把視頻嵌入到獨立站中&#xff1f; 前言 在信息傳播形式日益多元化的當下&#xff0c;靜態文字與圖片早已無法滿足用戶對沉浸式瀏覽體驗的需求。視頻以其動態畫面、聲音及文字相結合的特性…

【圖像處理基石】什么是攝影的數碼味?

“數碼味”是一個攝影術語&#xff0c;通常指照片看起來不自然&#xff0c;有過度處理的痕跡&#xff0c;比如色彩過于鮮艷、對比度偏高、高光過曝、陰影死黑&#xff0c;或者有明顯的銳化痕跡和噪點。這種現象在手機攝影中尤為常見&#xff0c;因為手機相機的自動算法往往會為…

報表控件stimulsoft教程:在報表、儀表板和 PDF 表單自動生成縮略圖

了解縮略圖的工作原理在使用Stimulsoft Demo、Stimulsoft Server和Stimulsoft Cloud時非常有用。例如&#xff0c;您可以在此處查看縮略圖的實際效果 - 當側邊欄折疊時&#xff0c;將顯示縮略圖而不是資源列表。在本文中&#xff0c;我們將探討 Stimulsoft 產品中報表、儀表板和…

變分自編碼器(VAE)

1. 從自編碼器&#xff08;AE&#xff09;到變分自編碼器&#xff08;VAE&#xff09; 自編碼器&#xff08;AutoEncoder, AE&#xff09; 基本結構: 自編碼器是一種無監督學習模型&#xff0c;通常由兩個部分組成&#xff1a; 編碼器&#xff08;Encoder&#xff09;&…

ChatboxAI 搭載 GPT 與 DeepSeek,引領科研與知識庫管理變革

文章摘要&#xff1a;本文深入探討 ChatboxAI 在科研領域的應用優勢。ChatboxAI 集成多模型&#xff0c;支持全平臺&#xff0c;能高效管理科研知識&#xff0c;助力文獻檢索、實驗設計與論文撰寫&#xff0c;提升科研效率與質量&#xff0c;同時保障數據安全。其知識庫功能可整…

【無刷電機FOC進階基礎準備】【04 clark變換、park變換、等幅值變換】

目錄 clark變換park變換等幅值變換 其實我不太記得住什么是clark變換、park變換&#xff0c;我每次要用到這個名詞的時候都會上網查一下&#xff0c;因為這就是兩個名詞而已&#xff0c;但是我能記住的是他們背后的含義。 經過【從零開始實現stm32無刷電機FOC】系列后應該對cla…

Sentinel的流控策略

在 Sentinel 中&#xff0c;流控策略&#xff08;Flow Control Strategy&#xff09;用于定義如何處理請求的流量&#xff0c;并決定在流量達到某個閾值時采取的行動。流控策略是實現系統穩定性和高可用性的核心機制&#xff0c;尤其在高并發環境中&#xff0c;確保服務不會因過…

Ubuntu Extension Manager 插件卸載

Ubuntu 上使用Extension Manager 安裝插件&#xff0c;但目前無法在Extension Manager 中卸載。 卸載方式可以通過 gnome-extensions 命令進行卸載&#xff1a; Usage:gnome-extensions COMMAND [ARGS…]Commands:help Print helpversion Print versionenable Enabl…

深度學習中Embedding原理講解

我們用最直白的方式來理解深度學習中 Embedding&#xff08;嵌入&#xff09; 的概念。 核心思想一句話&#xff1a; Embedding 就是把一些復雜、離散的東西&#xff08;比如文字、類別、ID&#xff09;轉換成計算機更容易理解和計算的“數字密碼”&#xff0c;這些“數字密碼…

(3)Java+Playwright自動化測試-啟動瀏覽器

1.簡介 前邊兩章文章已經將環境搭建好了&#xff0c;今天就在Java項目搭建環境中簡單地實踐一下&#xff1a; 啟動兩大瀏覽器。 接下來我們在Windows系統中啟動瀏覽器即可&#xff0c;其他平臺系統的瀏覽器類似的啟動方法&#xff0c;照貓畫虎就可以了。 但是在實踐過程中&am…

使用OpenWebUI與DeepSeek交互

Open WebUI 是針對 LLM 用戶友好的 WebUI,支持的 LLM 運行程序包括阿里百煉、 Ollama、OpenAI 兼容的 API。這里主要講在Docker環境下安裝與本地Ollame和百煉API Key配置 一、安裝Docker 1. CentOS # 設置為阿里云的源 sudo yum install -y yum-utils sudo yum-config-mana…

Github 2025-06-25 C開源項目日報 Top9

根據Github Trendings的統計,今日(2025-06-25統計)共有9個項目上榜。根據開發語言中項目的數量,匯總情況如下: 開發語言項目數量C項目9C++項目1raylib: 用于視頻游戲編程的簡單易用圖形庫 創建周期:3821 天開發語言:C協議類型:zlib LicenseStar數量:18556 個Fork數量:1…

【數據標注師】2D標注

目錄 一、 **2D標注知識體系框架**二、 **五階能力培養體系**? **階段1&#xff1a;基礎規則內化&#xff08;1-2周&#xff09;**? **階段2&#xff1a;復雜場景處理技能**? **階段3&#xff1a;專業工具 mastery**? **階段4&#xff1a;領域深度專精? **階段5&#xff1…