【每日八股】复习 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.mzph.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 和…