淺談mysql mvcc

目錄

前言

mvcc 是如何工作的?

數據的更新


前言

mvcc 與一個事物的隔離級別有關,未提交讀永遠讀的是當前值,串行化是通過加鎖實現,這兩種隔離級別都與mvcc 沒有任何關系。只要一提到mvcc應該想到的是讀提交以及可重復讀,大家有沒有想過都是mvcc,為啥這兩個隔離級別所呈現的結果有些不一樣呢?難道會有兩套mvcc 嗎?當然不是,對于這個問題,稍后我會說明的。

我先舉一個簡單的例子。下面是一個表的初始化語句。

CREATE TABLE `t` (`id` int(11) NOT NULL,`k` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1,1),(2,2);
sessionAsessionBsessionA

在此我說明下,sessionA 是在同一個事物下,事務的隔離級別是可重復讀,sessionB 是另外一個事物。是不是感覺很神奇,sessionB 對數據操作成功了,sessionA 沒有收到任何干擾。

是不是感覺sessionA 在begin 的時候像相機一樣為數據表拍了一張快照。而這個快照也是我們常說的一致性讀視圖即 consistent read view。它的作用是事務執行期間用來定義“我能看到什么數據”。

mvcc 是如何工作的?

在上面我們講到了快照,大家是不是感覺我在扯淡,100G的庫,你也去快照,你要拷貝100G的數據,別人不會拍死你,放心好了拍不死我的。

其實在啟動一個事物的時候,并不需要拷貝數據,只需要在事物系統申請一個事物id 叫做 transaction id,這個id 是原子遞增的,意味著一個數據庫不會出現兩個相同的事物id

每行數據也都是有多個版本的。每次事務更新數據的時候,都會生成一個新的數據版本,并且把 transaction id 賦值給這個數據版本的事務 ID,記為 row trx_id。同時,舊的數據版本要保留在undo log 里,并且在新的數據版本中,能夠有信息可以直接拿到它。

可以這么說,數據表中的一行記錄,其實可能有多個版本,每個版本都有自己的row trx_id。

按照可重復讀的定義,一個事物啟動的時候,能夠看到所有已經提交的事物結果。但是之后其他事物的更新,它卻看不見。

它是怎么找到自己能夠看見的數據呢,會拿到每個版本的 row trx_id,如果是在我啟動以后生成的row trx_id,繼續往前找,直到找到自己提交的或者是本事物啟動之前提交的。

為了方便比較,在實現上,innodb 為每個事物構建一個數組,用來保存這個事物啟動瞬間,當前正在“活躍” 的所有事物ID。“活躍” 指的是,啟動了還沒有提交的。

數組里面事務 ID 的最小值記為低水位,當前系統里面已經創建過的事務 ID 的最大值加 1 記為高水位。

這個視圖數組和高水位,就組成了當前事物的一致性視圖。

而數據版本的可見性規則,就是基于數據的 row trx_id 和這個一致性視圖的對比結果得到的。

就拿一致性視圖而言,規則是這樣的:

  1. 如果 row trx_id 小于這個視圖數組的最小值,說明已經提交了,那么這個數據就是可見的。

  2. 如果 row trx_id 大于這個高水位,肯定不可見呀,說明事物還沒有創建

  3. 如果 row trx_id 在 最小值和高水位之間又有兩種情況:row trx_id剛好就在視圖數組是說明還沒有提交也不可見,不在視圖數組里說明提交了就可見。

所以你現在知道了,InnoDB 利用了“所有數據都有多個版本”的這個特性,實現了“秒級創建快照”的能力。

所以一個數據版本,對于一個事務視圖來說,除了自己更新總是可見以外,有三種情況:

  1. 版本未提交,不可見;

  2. 版本已提交,但是是在視圖創建后提交的,不可見;

  3. 版本已提交,而且是在視圖創建前提交的,可見。

下面我在在回到最開始提到的那個問題,讀提交為啥又有些不一樣呢,讓我們在回顧一下什么是讀提交,在事務中,我們可以讀到已經提交的事物,只要在我事物中的任何一個時刻提交的,我都可以讀到。上面的規則對于讀提交同樣適用,只不過讀提交是在每個select語句都會去申請一個transaction id作為它的row trx_id,同時也會構建一個新的事物數組。

數據的更新

上面我們講到了mvcc,其實只是在select 用到,如果是update ,或者下面的語句。

select k from t where id=1 lock in share mode;
?
select k from t where id=1 for update;

大家都知道更新數據都是先讀后寫的,而這個讀,只能讀當前的值,稱為“當前讀”(current read)。

或者是select 語句加上了 share mode 共享鎖 或者 for update 拍他鎖,這些都只能用到當前讀,與mvcc 沒有一點關系了。

所以這些語句執行后,會對行進行加鎖,update 加行鎖,share mode 加的是讀鎖, for update 加的是寫鎖。讀到最新的數據

而這些鎖都是兩階段鎖,從加鎖開始到事物結束。這么做對于數據庫來說也是無賴之舉,為了保證數據的一致性,是數據的同步技術。

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

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

相關文章

vue+element ui上傳圖片到七牛云服務器

本來打算做一個全部都是前端完成的資源上傳到七牛云的demo,但是需要獲取token,經歷了九九八十一難,最終還是選擇放棄,token從后端獲取(springboot)。如果你們有前端直接能解決的麻煩記得私我哦!…

『Linux從入門到精通』第 ? 期 - 動靜態庫

文章目錄 💐專欄導讀💐文章導讀🐧什么是庫?🐧為什么要有庫?🐧寫一個自己的庫🐦方法一🐦方法二 靜態庫🐦標準化🐦方法三 動態庫🐦配置動…

python中自定義報錯

class MyError(Exception):def __init__(self,num):#錄入的數Exception.__init__(self)self.numnumdef __str__(self):return 這是我定義的第%d個異常 %(self.num)使用 try:raise MyError(4) except MyError as e:print(e)raise 其作用是指定拋出的異常名稱,以及異常…

題目 1240: 生日日數

題目描述: CCC老師的生日是YY年MM月DD日,他想知道自己出生后第一萬天紀念日的日期(出生日算第0天)。 代碼: package lanqiao;import java.time.LocalDate; import java.util.*;public class Main {public static void main(String[] args)…

數據結構題目①——數組

前言 本篇文章為博主進行代碼隨想錄——數組練習后的總結會涉及到每一道題目的詳細的思路整理,以及本人的易錯點,希望對大家有所幫助 數組介紹: 數組在C語言中就已經有所涉及,它是一個最基礎的數據結構,而在數據結構中…

Java學習—FileInputStream

在Java編程中,文件操作是日常任務之一。無論是讀取配置文件、處理圖像,還是讀寫日志文件,理解如何有效地進行文件讀取都是非常重要的。Java提供了多種方式來操作文件,而FileInputStream是其中最基礎也是最直接的一種。本文將深入探…

Spring面試系列-01

1. 什么是 Spring 框架? Spring中文翻譯過來是春天的意思,被稱為J2EE的春天,是一個開源的輕量級的Java開發框架, 具有控制反轉(IoC)和面向切面(AOP)兩大核心。Java Spring框架通過聲明式方式靈活地進行事務的管理,提高開發效率和質量。 Spring框架不僅限于服務器端的…

three 層級模型

group.remove(mesh1,mesh2);Vector3與模型位置、縮放屬性 Group層級模型(樹結構) 創建了兩個網格模型mesh1、mesh2,通過THREE.Group類創建一個組對象group,然后通過add方法把網格模型mesh1、mesh2作為設置為組對象group的子對象,然后在通過執行scene.a…

jenkins部署maven項目

流程: jenkins從代碼倉庫讀取代碼,將代碼文件放入jenkins的工作空間,將jenkins工作空間的代碼進行打包,將jar包遠程發送給服務器。 一:所需插件二:Tools 三:System: 配置ssh連接的…

github要求2fa身份驗證

前言 github登陸的時候發現要求2fa驗證, 2fa是啥?咋驗證? 解決 2FA(Two-Factor Authentication,雙因素身份驗證) 就是在賬戶和密碼的基礎上增加一次驗證碼驗證,這樣即使密碼被竊取,由于黑客沒有你的驗證碼也無法登陸 就像是銀行的u盾一樣…

python63-Python的循環之循環使用else

Python的循環都可以定義else代碼塊&#xff0c;當循環條件為False 時&#xff0c;程序會執行else代碼塊。如下代碼示范了為while循環定義else代碼塊。 # !/usr/bin/env python# -*- coding: utf-8 -*-# Time : 2024/01# Author : Laopicount_i 0while count_i < 5:print(c…

Java集合相關面試題(2024大廠高頻面試題系列)

1、說一說Java提供的常見集合&#xff1f;&#xff08;畫一下集合結構圖&#xff09; 在java中提供了量大類的集合框架&#xff0c;主要分為兩類&#xff1a; 第一個是Collection 屬于單列集合&#xff0c;第二個是Map 屬于雙列集合 在Collection中有兩個子接口List和Set。…

【力扣hot100】刷題筆記Day14

前言 又是新的一周&#xff0c;快樂的周一&#xff0c;快樂地刷題&#xff0c;今天把鏈表搞完再干活&#xff01; 114. 二叉樹展開為鏈表 - 力扣&#xff08;LeetCode&#xff09; 前序遍歷 class Solution:def flatten(self, root: Optional[TreeNode]) -> None:if not r…

回溯 Leetcode 51 N皇后

N皇后 Leetcode 51 學習記錄自代碼隨想錄 按照國際象棋的規則&#xff0c;皇后可以攻擊與之處在同一行或同一列或同一斜線上的棋子。 n 皇后問題 研究的是如何將 n 個皇后放置在 nn 的棋盤上&#xff0c;并且使皇后彼此之間不能相互攻擊。 給你一個整數 n &#xff0c;返回所…

Linux —— 鏈接文件

硬鏈接 一般情況下&#xff0c;文件名和inode號碼是"一一對應"關系&#xff0c;每個inode號碼對應一個文件名。但是&#xff0c;Unix/Linux系統允許&#xff0c;多個文件名指向同一個inode號碼。 這意味著&#xff0c;可以用不同的文件名訪問同樣的內容&#xff1b;對…

軟件開發常見模型解析

軟件開發常見模型解析 摘要&#xff1a;本文將為您詳細介紹軟件開發過程中常見的幾種模型&#xff0c;包括瀑布模型、敏捷開發模型、螺旋模型、迭代模型和原型模型。通過了解這些模型的原理、優缺點&#xff0c;幫助您在不同的軟件項目中選擇最適合的開發模型。 一、引言 在…

【IC前端虛擬項目】inst_buffer子模塊DS與RTL編碼

【IC前端虛擬項目】數據搬運指令處理模塊前端實現虛擬項目說明-CSDN博客 需要說明一下的是,在我所提供的文檔體系里,并沒有模塊的DS文檔哈,因為實際項目里我也不怎么寫DS畢竟不是每個公司都和HISI一樣對文檔要求這么嚴格的。不過作為一個培訓的虛擬項目,還是建議在時間充裕…

Docker技術概論(3):Docker 中的基本概念

Docker技術概論&#xff08;3&#xff09; Docker 中的基本概念 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://…

基于java+springboot女士電商平臺系統源碼+文檔設計

基于javaspringboot女士電商平臺系統源碼文檔設計 博主介紹&#xff1a;多年java開發經驗&#xff0c;專注Java開發、定制、遠程、文檔編寫指導等,csdn特邀作者、專注于Java技術領域 作者主頁 央順技術團隊 Java畢設項目精品實戰案例《1000套》 歡迎點贊 收藏 ?留言 文末獲取源…

C語言----動態內存管理(2)

1.這里總結動態內存管理里面的錯誤 &#xff08;1&#xff09;使用malloc開辟空間以后直接賦值 這個就是malloc開辟失敗返回空指針&#xff0c;直接給空指針賦值就是錯誤的&#xff0c; tip1:使用malloc開辟空間以后一定要判斷是否為空 &#xff08;2&#xff09; 越界訪問…