数据库事务的超级详细讲解,包括事务特性、事务隔离级别、MVCC(多版本并发控制)
数据库事务:
主要有事务特性,事务的隔离级别,MVCC。
事务特性:
事务(Transaction)是指作为单个逻辑工作单元执行的一系列操作,这些操作要么全部成功执行,要么全部不执行,不能出现部分执行的情况。事务具有以下四个特性,通常缩写为ACID:
1、原子性(Atomicity):事务是一个不可分割的工作单位,要么全部执行,要么全部不执行。如果事务中的任何一步操作失败,整个事务都会被回滚(Rollback),回到操作之前的状态,不会造成数据的损坏或不一致。
2、一致性(Consistency):事务在执行前后,数据库从一个一致性状态转移到另一个一致性状态。即使在事务执行过程中出现异常,数据库也会通过回滚操作,将数据恢复到一致性状态。
3、隔离性(Isolation):事务的执行不会受到其他事务的影响,每个事务在执行过程中都应该感觉不到其他事务的存在。即使多个事务同时操作同一数据,也不会互相干扰。隔离性能够防止并发事务导致的数据异常和不一致问题。
4、持久性(Durability):一旦事务被提交(Commit),其所做的修改将会永久保存在数据库中,并且即使系统发生故障,这些修改也不会丢失。数据库系统会将事务的修改持久化到磁盘中,以保证数据的持久性。
案例说明事务的特性:
假设有一个银行系统,用户 A 和用户 B 分别有 1000 元和 2000 元存款。用户 A 想要向用户 B 转账 500 元。这个转账操作可以通过以下 SQL 语句来实现:
sqlCopy Code-- 开启事务
START TRANSACTION;-- 扣除用户 A 的账户余额
UPDATE accounts SET balance = balance - 500 WHERE user_id = 'A';-- 增加用户 B 的账户余额
UPDATE accounts SET balance = balance + 500 WHERE user_id = 'B';-- 提交事务
COMMIT;
以上 SQL 语句实现了转账操作的原子性。如果在转账过程中发生了异常,比如数据库连接断开或者用户 A 的余额不足,那么整个事务都会被回滚,用户 A 和用户 B 的账户余额都会恢复到转账前的状态,确保了事务的一致性和持久性。
此外,隔离性的特点可以保证即使有其他用户同时查询用户 A 和用户 B 的账户余额,也不会受到转账操作的影响,保证了数据的隔离性。
隔离级别:
数据库事务的隔离级别定义了事务在并发执行时,系统如何控制事务之间的交互,即一个事务所做的更改在何时对其它事务可见。不同的隔离级别可以在并发性和一致性之间提供不同程度的平衡。SQL 标准定义了四种隔离级别,每种级别都可以减少一种或多种并发问题,但隔离级别越高,性能可能会越低,因为事务之间的并发能力减弱。
1. 读未提交(Read Uncommitted)
- 定义:最低的隔离级别,允许事务读取尚未提交的数据变更,可能会导致脏读、不可重复读和幻读。
- 问题:脏读。
- 案例:事务A修改了一条数据但尚未提交,事务B在此时读取了这条未提交的数据。如果A回滚,B读到的数据就是错误的。
2. 读已提交(Read Committed)
- 定义:允许事务读取并且仅读取已经提交的数据变更,可以避免脏读,但不可重复读和幻读仍可能发生。
- 问题:不可重复读。
- 案例:事务A读取了一条数据,事务B更新了这条数据并提交,当事务A再次读取同一数据时,数据已经变更。
3. 可重复读(Repeatable Read)
- 定义:确保如果一个事务读取了一条记录,则在这个事务剩余的时间里,无论其他事务如何更新,都不会影响到这条记录的读取结果。可以避免脏读和不可重复读,但幻读仍可能发生。
- 问题:幻读。
- 案例:事务A读取了几行数据,事务B插入了一行新数据并提交,当事务A再次查询同一范围的数据时,会看到之前未出现的新行。
4. 串行化(Serializable)
- 定义:最高的隔离级别,通过强制事务串行执行,避免脏读、不可重复读和幻读,但并发性能最差。
- 问题:性能问题。
- 案例:事务A和事务B需要操作同一数据集,B必须等待A完成并提交后,才能开始执行,从而保证了数据的一致性,但大大降低了并发性能。
并发问题解释:
- 脏读(Dirty Reads):事务读取了另一个事务未提交的数据。
- 不可重复读(Non-Repeatable Reads):事务在同一查询中多次读取同一数据集,结果却不同,因为其他事务在两次读取之间更新了数据。
- 幻读(Phantom Reads):事务在重新执行针对某个范围的查询时,发现其他事务插入了满足查询条件的新数据。
在选择隔离级别时,需要在数据一致性和系统性能之间做出权衡。高隔离级别能更好地保证数据的一致性,但可能会降低系统的并发性能;低隔离级别虽然并发性能较好,但在数据一致性上可能存在缺陷。
MVCC:
MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种数据库事务并发控制的方法,主要用于解决读-写冲突,实现高并发访问数据库而不会出现数据不一致的情况。MVCC通过在数据库中保存数据的不同版本来实现并发控制,每个事务在执行时看到的数据版本都是一致的,但不同事务之间可以并发执行而不会相互影响。
MVCC实现原理:
1. 数据版本控制:
MVCC的核心思想是为每个数据项维护多个版本,并且每个事务只能看到适合自己版本的数据。数据库中的每个数据项都会有一个版本号或者时间戳与之关联。
- 版本号:可以是整数或者时间戳,用于标识数据版本的顺序。
- 时间戳:记录数据版本的生成时间,通常精确到毫秒或更高精度。
2. 版本链:
数据库中的数据通常以行(Row)为单位存储,每一行数据可能会有多个版本,这些版本按照时间顺序形成一个版本链。版本链可以用一个双向链表或者类似的数据结构来实现。
- 每个数据行的版本链:包含了该数据行的所有版本,按照时间顺序排列。
- 链表节点:存储了数据的具体内容以及指向下一个版本的指针。
3. 读操作实现:
当一个事务要执行读操作时,它会根据自己的事务ID或者时间戳确定要读取的数据版本,然后遍历该数据行的版本链,找到最接近但不超过事务版本的数据版本。
- 快照读(Snapshot Read):事务读取数据时不会阻塞其他事务对同一数据的写操作,而是读取数据版本链中对应版本的数据。
- 读取过程:事务通过版本链中的版本号或者时间戳来定位数据,确保读取到的数据是在该事务开始之前已经提交的。
4. 写操作实现:
当一个事务要执行写操作时,它会为数据生成一个新版本,并将新版本插入到数据行的版本链中。通常会使用写时复制(Copy-On-Write)或者类似的机制来实现写操作。
- 生成新版本:事务会生成一个新的版本号或者时间戳,并将新版本写入到数据库中。
- 写时复制:旧版本的数据不会立即被覆盖,而是在新版本生成后才被修改,这样可以保留旧版本的数据用于事务的隔离和回滚。
5. 提交操作实现:
当一个事务提交时,它会释放对数据库的锁,并清理与该事务相关的数据版本。这通常包括将该事务生成的新版本标记为已提交,并删除回滚段中与该事务相关的数据。
- 释放锁:事务提交后,其他事务可以访问该数据,并且可以读取该事务生成的新版本。
- 清理数据:删除回滚段中与该事务相关的数据,确保数据库的存储空间得到有效利用。
6. 事务隔离级别:
MVCC可以实现不同的事务隔离级别,包括读未提交、读已提交、可重复读和串行化。不同的隔离级别决定了事务对数据的读取和写入行为,从而影响了并发控制的实现方式。
- 隔离级别:用于控制事务之间的相互影响程度,包括读取到的数据版本以及事务的可见性等方面。
总结:
MVCC通过多版本控制和版本链来实现数据库的并发控制,保证了事务之间的隔离性,从而确保了数据的一致性和完整性。MVCC是许多现代数据库系统的核心技术之一,如MySQL、PostgreSQL等都采用了MVCC来实现事务的并发控制。
MVCC实现流程:
当一个事务开始时,数据库系统会为其分配一个唯一的事务ID或者时间戳,并根据该事务ID或时间戳来执行读取和写入操作。
1. 读操作流程:
- 事务开始:事务T开始时,获取一个唯一的事务ID或时间戳。
- 确定读取版本:根据事务T的隔离级别,确定要读取的数据版本:
- 如果隔离级别是读未提交,则可以读取到其他未提交事务的数据。
- 如果隔离级别是读已提交或更高级别,则只能读取已提交事务生成的数据版本。
- 读取数据:根据确定的数据版本,从数据库中读取数据。通常是通过版本链中的版本号或时间戳来定位数据。
- 提交或回滚:如果读取数据时发现该数据已被删除或不可见,则根据事务的隔离级别决定是提交还是回滚该事务。
2. 写操作流程:
- 事务开始:事务T开始时,获取一个唯一的事务ID或时间戳。
- 生成新版本:为要写入的数据生成一个新版本,并将新版本插入到数据行的版本链中。通常采用写时复制或类似的机制来实现。
- 写入数据:将新版本的数据写入到数据库中。此时,其他事务仍然可以读取旧版本的数据,保持了数据的一致性。
- 提交或回滚:事务T完成所有写操作后,根据事务的提交或回滚指令来决定是否将写入的数据版本提交或回滚。
- 如果提交事务,则将新版本标记为已提交,其他事务可以读取该版本。
- 如果回滚事务,则删除新版本,并保留旧版本的数据。
3. 并发控制流程:
- 读-写冲突检测:当一个事务T1要读取数据时,如果发现有其他事务T2正在对该数据进行写操作,则需要进行冲突检测。
- 如果T2的写操作已提交,则T1可以读取T2提交的新版本。
- 如果T2的写操作未提交,则根据事务隔离级别决定是否允许T1读取T2的未提交数据。
- 写-写冲突检测:当一个事务T1要对数据进行写操作时,如果发现有其他事务T2正在对同一数据进行写操作,则需要进行冲突检测。
- 如果T2的写操作已提交,则T1需要等待T2完成后再进行写操作。
- 如果T2的写操作未提交,则根据事务隔离级别决定是否允许T1覆盖T2的未提交数据。
- 事务隔离级别的控制:根据事务的隔离级别,决定事务对数据的读取和写入行为,从而控制事务之间的相互影响程度。
- 并发度控制:根据系统的并发度限制,控制同时执行的事务数量,避免系统过载和性能下降。
4. 事务提交流程:
- 提交指令:当一个事务T完成所有操作后,执行提交指令。
- 标记提交:将事务T生成的新版本标记为已提交状态,其他事务可以读取该版本。
- 释放锁:释放事务T持有的锁资源,其他事务可以对相应数据进行读写操作。
- 清理数据:删除回滚段中与事务T相关的数据版本,释放存储空间。
- 提交完成:事务T提交完成,其他事务可以读取其写入的数据版本。
MVCC通过以上流程实现了数据库的并发控制,保证了事务之间的隔离性和数据的一致性。
MVCC案例说明:
假设有一个简单的数据库表,记录了用户的姓名和年龄,初始数据如下:
ID | Name | Age |
---|---|---|
1 | Alice | 25 |
2 | Bob | 30 |
现在有两个事务,T1 和 T2,分别对数据库进行操作:
- 事务 T1:
- T1 开始,读取 ID 为 1 的用户信息,姓名为 Alice,年龄为 25。
- T1 更新 ID 为 1 的用户信息,将年龄增加 1,变为 26。
- T1 提交事务。
- 事务 T2:
- T2 开始,读取 ID 为 1 的用户信息,姓名为 Alice,年龄为 25。此时由于T1未提交,T2读取到的是旧版本的数据。
- T2 提交事务。
通过MVCC,事务T2读取到了ID为1的用户信息时,虽然T1已经对该数据进行了更新,但T2读取到的是旧版本的数据,这样就避免了T2读取到脏数据的情况。
总的来说,MVCC通过版本控制实现了数据库的高并发访问,保证了事务之间的隔离性,从而确保了数据的一致性。
相关文章:
数据库事务的超级详细讲解,包括事务特性、事务隔离级别、MVCC(多版本并发控制)
数据库事务: 主要有事务特性,事务的隔离级别,MVCC。 事务特性: 事务(Transaction)是指作为单个逻辑工作单元执行的一系列操作,这些操作要么全部成功执行,要么全部不执行ÿ…...

鸿蒙Lottie动画-实现控制动画的播放、暂停、倍速播放、播放顺序
介绍 本示例展示了lottie对动画的操作功能。引入Lottie模块,实现控制动画的播放、暂停、倍速播放、播放顺序、播放到指定帧停止或从指定帧开始播放、侦听事件等功能,动画资源路径必须是json格式。 效果预览 使用说明: 进入页面默认开始201…...
C++面试100问与自动驾驶100问
C的学习和面试其实是非常的不友好的,首先C的学习内容非常的多,其次C的面试不单单面试C的知识点,还有它的“七大姑八大姨”(计算机网络、数据结构、算法、计算机组成原理、操作系统、编译、xxx的底层实现 and so on)。 …...
加速 Redis 操作:掌握管道技术提升性能与效率
Redis 管道技术是一种用于优化 Redis 命令执行效率的机制。在传统的 Redis 操作中,每次向 Redis 服务器发送一个命令,都需要等待命令执行完成并返回结果,这样会导致频繁的网络通信和服务器端的命令执行开销,降低系统的性能和吞吐量…...

深入浅出 -- 系统架构之分布式系统底层的一致性
在分布式领域里,一致性成为了炙手可热的名词,缓存、数据库、消息中间件、文件系统、业务系统……,各类分布式场景中都有它的身影,因此,想要更好的理解分布式系统,必须要理解“一致性”这个概念。 其实关于…...

idea Springboot 电影推荐系统LayUI框架开发协同过滤算法web结构java编程计算机网页
一、源码特点 springboot 电影推荐系统是一套完善的完整信息系统,结合mvc框架和LayUI框架完成本系统springboot dao bean 采用协同过滤算法进行推荐 ,对理解JSP java编程开发语言有帮助系统采用springboot框架(MVC模式开发)&…...

xss【2】
1.xss钓鱼 钓鱼攻击利用页面,fish.php黑客钓鱼获取到账号密码存储的位置 xss进行键盘记录 2.xss常规防范 3.xss验证payload XSS(跨站攻击)_details/open/ontoggle-CSDN博客...

时序分解 | Matlab实现GSWOA-VMD改进鲸鱼优化算法优化变分模态分解时间序列信号分解
时序分解 | Matlab实现GWO-CEEMDAN基于灰狼算法优化CEEMDAN时间序列信号分解 目录 时序分解 | Matlab实现GWO-CEEMDAN基于灰狼算法优化CEEMDAN时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现GSWOA-VMD改进鲸鱼优化算法优化变分模态分解时间序…...

css- 4
1.浮动 1. 浮动最初用于实现文字环绕效果 2. 现在,浮动是主流的布局方式之一 1.1元素浮动之后的特点 元素浮动之后,称为浮动元素,具有如下特点: 1. 浮动元素脱离文档流 2. 多个浮动的元素会水平排列,一行放不下自动换…...
22.括号生成
题目描述 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示例 1: 输入:n 3 输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”] 示例 2: 输入…...

JAVA八股--redis
JAVA八股--redis 如何保证Redis和数据库数据一致性redisson实现的分布式锁的主从一致性Redis脑裂现象及解决方案介绍I/O多路复用模型undo log 和 redo log(没掌握MyISAM 和 InnoDB 有什么区别? 如何保证Redis和数据库数据一致性 关于异步通知中消息队列…...

[图像处理] MFC载入图片并绘制ROI矩形
上一篇: [图像处理] MFC载入图片并进行二值化处理和灰度处理及其效果显示 文章目录 前言完整代码重要代码效果 前言 上一篇实现了MFC通过Picture控件载入图片。 这一篇实现ROI功能的第一部分,在Picture控件中,通过鼠标拖拽画出一个矩形。 完…...

Godot 4 教程《勇者传说》依赖注入 学习笔记(0):环境配置
文章目录 前言相关地址环境配置初始化环境配置文件夹结构代码结构代码运行 资源文件导入像素风格窗口环境设置背景设置,Tileap使用自动TileMap 人物场景动画节点添加站立节点添加移动动画添加 通过依赖注入获取Godot的全局属性项目声明 当前项目逻辑讲解角色下降添加代码位置问…...
强行让Java和Go对比一波[持续更新]
概述 很多Java开发如果想转Golang的话,比较让Java开发蛋疼的第一是语法,第二是一些思想和设计哲学的Gap,所以我这儿强行整理一波Java和Golang的对比,但是由于GO和Java在很多方面都有不同的设计,所以这些对比的项可以更…...
理解七层网络协议
osi体系结构 上三路(管数据) 应用层 通过http等,把传输的格式,数据打包 处理网络应用。直接为端用户服务,提供各类应用过程的接口和用户接口。例如:HTTP、Tenlent、FTP、SMTP、NFS等。基于TCP的FTP、HTTP…...

网络协议——HTTP协议
目录 编辑 一,HTTP协议基本认识 二,认识URL 三,http协议的格式 1,发送格式 2,回应格式 四,服务端代码 五,http报文细节 1,Post与Get方法 2,Content_lenth 3&…...

八股面试——数据库——索引
索引的概念 B树的概念: 索引的作用 聚簇索引与非聚簇索引 聚簇索引就是主键值,在B树上,通过主键大小(数据在B树叶子节点按主键顺序排序)寻找对应的叶子节点,叶子节点保存的一整条记录。 非聚簇索引&#x…...

【二分查找】Leetcode 二分查找
题目解析 二分查找在数组有序可以使用,也可以在数组无序的时候使用(只要数组中的一些规律适用于二分即可) 704. 二分查找 算法讲解 当left > right的时候,我们循环结束,但是当left和right缩成一个点的时候&#x…...

Python+Vuecil笔记
Nginx 进入目录: C:\nginx-1.20.2\nginx-1.20.2 start nginx 开始 nginx -s stop 停止 nginx -s quit 退出CSS 通过标签去写css 循环展示数据 JS 点击时执行事件 Django 配置media 在seetings里面修改 STATIC_URL /static/ MEDIA_URL /upload/ MEDIA_ROOT os.pat…...
C语言关于随机数知识点的总结
在C语言中,随机数的生成通常依赖于特定的库函数,最常用的是 <stdlib.h> 头文件中的 rand() 函数。以下是对随机数知识点的总结、举例和分析: 随机数知识点总结 1.随机数种子:rand() 函数生成的随机数是伪随机数࿰…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...