【每日八股】復習 MySQL Day1:事務

文章目錄

  • 復習 MySQL Day1:事務
    • MySQL 事務的四大特性?
    • 并發事務會出現什么問題?
    • MySQL 事務的隔離級別?
    • 不同事務隔離級別下會發生什么問題?
    • MVCC 的實現原理?
      • 核心數據結構
      • 版本鏈構建示例
      • 可見性判斷算法
      • MVCC 可見性判斷總結
    • 幻讀如何解決?
    • 讀已提交隔離級別如何實現?

復習 MySQL Day1:事務

在這里插入圖片描述

MySQL 事務的四大特性?

  • 原子性:事務當中的若干條數據庫操作要么全部成功,要么全部失敗;
  • 一致性:數據庫總是從一個一致性的狀態遷移到另一個一致性的狀態;
  • 隔離性:事務提交之前,對數據庫做出的更改對其他事務不可見;
  • 持久性:事務提交之后就會被持久化到磁盤當中。

并發事務會出現什么問題?

指的主要是由 MySQL 隔離級別的不同帶來的若干問題。

  • 臟讀:事務還未提交,其所做的修改就已經可以被其他事務所讀取了;
  • 不可重復讀:事務開始時讀取的數據與事務執行過程中讀取到的數據不同;
  • 幻讀:通常發生在區間查詢的場景下,指的是在一個事務執行期間內,上一次范圍查詢讀取到的數據與本次范圍查詢讀取到的數據不一致,其發生的原因可能是在事務執行期間有其他事務向第一次查詢的數據區間當中插入了新的數據。

MySQL 事務的隔離級別?

  • 讀未提交:事務還未提交,其他事務就可看到其所做的更改,隔離級別最低;
  • 讀已提交:事務提交之后,其所做的更改才能夠被其他事務所看到。在讀已提交隔離級別下,當前事務可以看到其他事務執行完成后所做的修改;
  • 可重復讀:MySQL InnoDB 數據引擎的默認隔離級別,指的是從事務開始到事務結束期間,讀取到的數據都是一致的;
  • 串行化:對記錄加上讀寫鎖,在多個事務進行讀寫的過程中,如果發生了鎖沖突,那么當前事務必須等上一個事務讀寫完成方可進行讀寫。串行化不存在并發事務的問題,但它的并發性能最差。

不同事務隔離級別下會發生什么問題?

  • 讀未提交:臟讀、不可重復讀、幻讀;
  • 讀已提交:不可重復讀、幻讀;
  • 可重復讀:幻讀;
  • 串行化:不存在并發事務的問題;

MVCC 的實現原理?

MVCC 是數據庫實現并發控制的關鍵技術,InnoDB 數據引擎通過 MVCC 實現讀操作的并發,極大提高了數據庫的并發性能。

核心數據結構

隱藏字段
InnoDB 為每行記錄添加了以下隱藏字段:

  • DB_TRX_ID:記錄創建或最后一次修改該行記錄的事務 ID;
  • DB_ROLL_PTR:回滾指針,指向 undo log 記錄;
  • DB_ROW_ID:隱含的自增行 ID;
  • DELETE BIT:記錄該行是否刪除。

Undo Log(回滾日志)

  • 存儲行記錄的歷史版本;
  • 組成版本鏈,通過 DB_ROLL_PTR 指針連接;
  • 用于事務回滾與 MVCC 讀取。

Read View(讀視圖)

  • m_ids:生成 Read View 時活躍的事務 ID 列表;
  • min_trx_id:m_ids 中的最小事務 ID;
  • max_trx_id:m_ids 中的最大事務 ID;
  • create_trx_id:創建該 Read View 的事務 ID。

版本鏈構建示例

  1. 每次更新操作都會在 undo log 記錄舊數據版本;
  2. 通過 DB_ROLL_PTR 指針形成單向鏈表;
  3. 鏈表頭是最新版本,尾部是最舊版本。

可見性判斷算法

比較 DB_TRX_ID 與 creator_trx_id
如果相等,說明當前記錄是該事務自身修改的事務,對當前事務可見。

檢查 DB_TRX_ID < min_trx_id
說明這條記錄在當前 Read View 生成之前已經提交,對當前事務可見。

檢查 DB_TRX_ID >= max_trx_id
說明這條記錄是在 Read View 生成之后創建的,對當前事務不可見。

檢查 DB_TRX_ID 是否在 m_ids 事務活躍列表當中

  • 存在:生成 Read View 時當前記錄仍活躍,對當前事務不可見;
  • 不存在:最后一次修改該條記錄的事務已提交,對當前事務可見;

MVCC 可見性判斷總結

總的來說,針對基于 MVCC 的事務可見性判斷,關鍵的字段包括以下幾個:

  • 對于記錄,每一條記錄都有一個隱式的 DB_TRX_ID 字段,用于記錄最后一個修改這條記錄的事務 ID;
  • 對于 SELECT 操作生成的 Read View,其隱式包含以下幾個字段:
    1)m_ids:Read View 生成時活躍的事務 ID 列表;
    2)min_trx_id:m_ids 中最小的事務 ID;
    3)max_trx_id:m_ids 中最大的事務 ID;
    4)create_trx_id:創建這個 Read View 的事務 ID。

可見性判斷的算法流程如下:

  1. 首先對比記錄的 DB_TRX_ID 和 creator_trx_id,相等則代表該記錄最后一次由當前視圖修改,對該事務可見;
  2. 之后再比對 DB_TRX_ID 和 min_trx_id 以及 max_trx_id 的大小,如果小于 min_trx_id,說明修改該記錄的事務在生成 Read View 時已提交,對當前事務可見;如果大于 max_trx_id,說明修改該記錄的事務在當前事務之后創建,其所做的修改對當前事務不可見,通過 DB_ROLL_PTR 找到該記錄的上一個版本。
  3. 最后查看 DB_TRX_ID 是否在 m_ids 當中,如果在,說明修改這條記錄的事務在活躍列表當中,該記錄的當前版本對當前事務不可見;否則說明修改該記錄的事務已經提交,這條記錄對當前事務可見。

幻讀如何解決?

通過快照讀(一致性非鎖定讀)
對于普通的 SELECT 查詢語句,InnoDB 使用 MVCC 提供一致性視圖,避免看到其他事務插入的數據。

使用間隙鎖(Gap Lock)和臨鍵鎖(Next-Key Lock)
InnoDB 在可重復讀隔離級別下通過以下方式防止幻讀:

  • 間隙鎖(Gap Lock):鎖定索引記錄之間的間隙;
  • 臨鍵鎖(Next-Key Lock):臨鍵鎖是記錄鎖(行鎖)+ 間隙鎖的組合,鎖定記錄及其前面的間隙。

一個基于間隙鎖 + 臨鍵鎖防止幻讀的例子如下:

-- 事務1
BEGIN;
SELECT * FROM users WHERE age > 20 FOR UPDATE; -- 鎖定age>20的所有記錄和間隙
-- ?? 顯式地使用區間鎖鎖定一個范圍, 避免在范圍內有新記錄插入
-- 此時事務2嘗試插入age>20的記錄會被阻塞
INSERT INTO users(name, age) VALUES('new_user', 25); -- 阻塞

總結
使用「MVCC 版本控制」或「間隙鎖 + 臨鍵鎖」這兩種方式可以避免幻讀的問題。

讀已提交隔離級別如何實現?

在讀已提交隔離級別下,每次執行 SELECT 語句都會創建一個 Read View。創建 Read View 時已經提交的事務所做的修改對當前事務是可見的(會導致不可重復讀問題),但未提交以及當前事務之后的事務所做的修改不可見。

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

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

相關文章

在極狐GitLab 身份驗證中如何使用 OIDC?

極狐GitLab 是 GitLab 在中國的發行版&#xff0c;關于中文參考文檔和資料有&#xff1a; 極狐GitLab 中文文檔極狐GitLab 中文論壇極狐GitLab 官網 使用 OpenID Connect 作為認證提供者 (BASIC SELF) 您可以使用極狐GitLab 作為客戶端應用程序&#xff0c;與 OpenID Connec…

PHP騰訊云人臉核身生成 SDK 接口調用步驟使用簽名

參考騰訊云官方文檔&#xff1a; 人臉核身 生成 SDK 接口調用步驟使用簽名_騰訊云 前提條件&#xff1a;成功獲取NonceTicket。 獲取參考文檔&#xff1a; PHP騰訊云人臉核身獲取NONCE ticket-CSDN博客 function getTxFaceSign(){$appId ;$userId ;$version 1.0.0;$tic…

每日一題算法——鏈表相交

鏈表相交 力扣題目鏈接 暴力解法:飄過 class Solution { public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {ListNode * cur headA;while(cur ! NULL){ListNode* curb headB;while(curb ! NULL){if(curbcur){return cur;}curb curb->next;}cu…

詳解Windows(一)——系統盤下目錄及文件詳解

引言 你是否曾經好奇過電腦里那些神秘的文件夾都是干什么用的&#xff1f;為什么有些文件是.exe而有些是.dll&#xff1f;不同的圖片格式.jpg和.png到底有什么區別&#xff1f;如果你對這些問題感到困惑&#xff0c;這篇文章就是為你準備的。今天&#xff0c;我們將以通俗易懂…

大模型賦能工業制造革新:10個顯效可落地的應用場景

在工業4.0的洶涌浪潮中&#xff0c;制造業正面臨著前所未有的轉型挑戰。傳統制造模式在效率、成本、質量等方面逐漸難以滿足市場需求&#xff0c;企業急需借助新技術實現數字化轉型&#xff0c;以提升自身競爭力。在此背景下&#xff0c;基于先進的數據分析技術、大模型、知識圖…

AI語音助手 React 組件使用js-audio-recorder實現,將獲取到的語音轉成base64發送給后端,后端接口返回文本內容

頁面效果&#xff1a; js代碼&#xff1a; import React, { useState, useRef, useEffect } from react; import { Layout, List, Input, Button, Avatar, Space, Typography, message } from antd; import { SendOutlined, UserOutlined, RobotOutlined, AudioOutlined, Stop…

pycharm無法識別到本地python的conda環境解決方法

問題一 現象描述&#xff1a; 本地已經安裝了conda&#xff0c;但在pycharm中選擇conda環境卻識別不到&#xff0c; 解決方法&#xff1a;手動輸入conda path&#xff0c;點擊R eload environments基本就能修復&#xff0c;比如我的路徑如下 /Users/test/conda/miniconda3/b…

PDK中technology file從tf格式轉換為lef格式

在數字后端流程中需要導入technology file工藝文件&#xff0c;一般傳統的PDK中都提供.tf形式&#xff0c;能夠在Synopsys ICC中進行導入。但是由于Cadence Innovus不斷地完善&#xff0c;更多的工程采用了其進行數字后端設計。不過Cadence Innovus導入的是.lef格式的工藝文件&…

UE虛幻4虛幻5動畫藍圖調試,觸發FellOutOfWorld事件和打印輸出,繼續DeepSeek輸出

找到了一個pdf&#xff0c;本來想寫個翻譯的&#xff0c;但還是算了&#xff0c;大概看了下&#xff0c;這類文檔很全面&#xff0c;內容很多&#xff0c;但都不是我要的&#xff0c;我想要一個動畫藍圖&#xff0c;搜索Montage&#xff0c;或者Anim 只占了一行&#xff08;幾百…

【Sa-Token】學習筆記05 - 踢人下線源碼解析

目錄 前言 強制注銷 踢人下線 源碼解析 前言 所謂踢人下線&#xff0c;核心操作就是找到指定 loginId 對應的 Token&#xff0c;并設置其失效。 上圖為踢人下線后&#xff0c;前端應該用圖像給出來讓用戶重新登錄&#xff0c;而不是讓前端收到一個描述著被下線 的JSON 強…

C語言==》字符串斷行

示例代碼 #include <stdio.h>int main(void) {printf("Heres one way to print a ");printf("long string.\n");printf("Heres another way to print a \ long string.\n");printf("Heres the newest way to print a ""lo…

Linux | I.MX6ULL 文件系統

01 本節所有的測試程序需要開發板有 Qt 環境來運行。我們提供的文件系統是由 yocto 裁剪整理得來的。之后我們會整理一份單獨移植的 qt 系統。方便用戶移植第三方軟件。如果用戶的文件系統非我們的出廠版本,請參考之前燒寫章節重新燒寫出廠文件系統。開發板啟動需要輸入登錄…

網絡原理 - 應用層, 傳輸層(UDP 和 TCP) 進階, 網絡層, 數據鏈路層 [Java EE]

目錄 應用層 1. 應用層的作用 2. 自定義應用層協議 3. 應用層的 "通用協議格式" 3.1 xml 3.2 json 3.3 protobuffer (pd) 傳輸層 1. UDP 1.1 無連接 1.2 不可靠傳輸 1.3 面向數據報 1.4 全雙工 1.5 緩沖區 1.6 UDP 數據報 2. TCP 2.1 有連接 …

如何將自己封裝的組件發布到npm上:詳細教程

如何將自己封裝的組件發布到npm上&#xff1a;詳細教程 作為前端開發者&#xff0c;我們經常從npm&#xff08;Node Package Manager&#xff09;上下載并使用各種第三方庫和組件。然而&#xff0c;有時候我們可能會發現自己需要的功能在npm上并不存在&#xff0c;或者我們希望…

[OS_7] 訪問操作系統對象 | offset | FHS | Handle

實驗代碼可以看去年暑假的這篇文章&#xff1a;【Linux】進程間通信&#xff1a;詳解 VSCode使用 | 匿名管道 我們已經知道&#xff0c;進程從 execve 后的初始狀態開始&#xff0c;可以通過 mmap 改變自己的地址空間&#xff0c;通過 fork 創建新的進程&#xff0c;再通過 exe…

關于TCP三次握手和四次揮手過程中的狀態機、使用三次握手和四次揮手的原因、擁塞控制

關于傳輸層中的TCP協議&#xff0c;我們在之前的博客中對其報文格式、三次握手、四次揮手、流量控制、數據傳輸等機制進行了具體說明&#xff0c;接下來在前面所學的基礎上&#xff0c;我們再來講講TCP中三次握手和四次揮手各階段所處的狀態機以及為什么要使用三次握手和四次揮…

學習筆記二十——Rust trait

&#x1f9e9; Rust Trait 徹底搞懂版 &#x1f440; 目標讀者&#xff1a;對 Rust 完全陌生&#xff0c;但想真正明白 “Trait、Trait Bound、孤島法則” 在做什么、怎么用、為什么這樣設計。 &#x1f6e0; 方法&#xff1a; 先給“心里模型”——用生活類比把抽象概念掰開揉…

es 混合檢索多向量

在結合向量相似度檢索的同時,可以通過 bool 查詢的 filter 或 must 子句實現關鍵詞過濾。以下是一個同時包含 關鍵詞匹配 和 多向量相似度計算 的完整示例: 參考博文:ES集群多向量字段檢索及混合檢索方法-CSDN博客 示例:帶關鍵詞過濾的多向量聯合檢索 GET /my_index/_sea…

HTML5好看的水果蔬菜在線商城網站源碼系列模板4

文章目錄 1.設計來源1.1 主界面1.2 關于我們1.3 商品信息1.4 新聞資訊1.5 聯系我們1.5 登錄注冊 2.效果和源碼2.1 動態效果2.2 源代碼 源碼下載 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/147264262 HTML5好看的水果…

Kubernetes(k8s)學習筆記(二)--k8s 集群安裝

1、kubeadm kubeadm 是官方社區推出的一個用于快速部署 kubernetes 集群的工具。這個工具能通過兩條指令完成一個 kubernetes 集群的部署&#xff1a; 1.1 創建一個 Master 節點$ kubeadm init 1.2 將一個 Node 節點加入到當前集群中$ kubeadm join <Master 節點的 IP 和…