第26章_事务概述与隔离级别
文章目录
- 事务
- 事务的特征
- 事务的控制语句
- 事务的生命周期
- 事务的执行过程
- ACID特性
- 原子性
- 一致性
- 隔离性
- 持久性
- 隔离级别
- 不同隔离级别并发异常
- 脏读
- 不可重复读
- 幻读
- 区别
- 总结
事务
(1)事务的前提:并发连接访问。MySQL的事务就是将多条SQL语句作为整体进行执行。
(2)事务的定义:用户定义的一系列SQL操作,这些操作要么都执行,要么都不执行,是一个不可分割的单位。
(3)事务的本质是并发控制的单元,是用户定义的一个操作序列。这些操作要么都做,要么都不做,是一个不可分割的工作单元。
(4)事务的目的:事务将数据库从一种一致性状态转换为另一种一致性状态;保证系统始终处于一个完整且正确的状态。
(5)事务的组成:事务可由一条非常简单的SQL语句组成,也可以由一组复杂的SQL语句组成。
事务的特征
在数据库提交事务时,可以确保要么所有修改都已经保存,要么所有修改都不保存。事务是访问并更新数据库各种数据项的一个程序执行单元。
在 MySQL innodb 下,单条语句都具备事务;可以通过 set autocommit = 0; 设置当前会话手动提交。
事务的控制语句
-- 显示开启事务
START TRANSACTION | BEGIN
-- 提交事务,并使得已对数据库做的所有修改持久化
COMMIT
-- 回滚事务,结束用户的事务,并撤销正在进行的所有未提交的修改
ROLLBACK
-- 创建一个保存点,一个事务可以有多个保存点
SAVEPOINT identifier
-- 删除一个保存点
RELEASE SAVEPOINT identifier
-- 事务回滚到保存点
ROLLBACK TO [SAVEPOINT] identifier
事务的生命周期
(1)begin … commit。从开始事务到提交事务。
(2)begin … rollback。从开始事务到事务回滚。
事务的执行过程

ACID特性
原子性
事务操作要么都做(提交),要么都不做(回滚)。事务是访问并更新数据库各种数据项的一个程序执行单元,是不可分割的工作单位。
MySQL通过 undolog 来实现回滚操作。undolog 记录的是事务每步具体操作,当回滚时,回放事务具体操作的逆运算。
事务包含的全部操作是一个不可分割的整体,要么全部执行,要么全部不执行。
假如数据库的事务执行到一半,数据库突然宕机,那么宕机前执行的SQL语句不会生效,undolog 会把它回滚到事务开始之前的数据。
undolog是会记录DML操作的日志,回滚就是依赖undolog日志,用来帮助回滚事务的。
一致性
事务的前后,所有的数据都保持一个一致的状态,不能违反数据的一致性检测(完整性约束检查)。
一致性指事务将数据库从一种一致性状态转变为下一种一致性的状态,在事务执行前后,数据库完整性约束没有被破坏;一个事务单元需要提交之后才会被其他事务可见。例如:一个表的姓名是唯一键,如果一个事务对姓名进行修改,但是在事务提交或事务回滚后,表中的姓名变得不唯一了,这样就破坏了一致性。
一致性 有数据库完整约束和逻辑上一致性(比如因为多个事务共同操作银行卡导致钱财不一致问题)。
一致性由原子性、隔离性以及持久性共同来维护的。
隔离性
描述:各个事务之间互相影响的程度。
目的:主要规定多个事务访问同一数据资源,各个事务对该数据资源访问的行为,不同的隔离性是应对不同的现象(脏读、不可重复读、幻读)。
事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,并发事务之间不会相互影响,设定了不同程度的隔离级别,通过适度破环一致性,得以提高性能。
隔离性 通过 MVCC和 锁来实现。MVCC是多版本并发控制,主要解决一致性非锁定读,通过记录和获取行版本,而不是使用锁来限制读操作,从而实现高效并发读性能。锁用来处理并发 DML 操作。
数据库中提供粒度锁的策略,针对表(聚集索引 B+ 树)、页(聚集索引 B+ 树叶子节点)、行(叶子节点当中某一段记录行)三种粒度加锁。
持久性
事务一旦完成,要将数据所做的变更记录下来,包括数据存储和多副本的网络备份。
事务提交后,事务 DML 操作将会持久化(写入 redolog 磁盘文件 哪一个页 页偏移值 具体数据);即使发生宕机等故障,数据库也能将数据恢复。
redolog 记录的是物理日志。
隔离级别
隔离级别的目的是提升并发性能。隔离级别越高,事务之间的影响级别最低,同时效率也是最低。隔离级别中,所有写操作都要加锁,唯一不同的是读操作,不同的隔离级别读操作的加锁程度不一样。
ISO 和 ANIS SQL 标准制定了四种事务隔离级别的标准,各数据库厂商在正确性和性能之间做了妥协,并没有严格遵循这些标准。MySQL innodb默认支持的隔离级别是 REPEATABLE READ。
降低隔离级别都会影响一致性,准确的说是影响逻辑上的一致性。
(1) READ UNCOMMITTED。读未提交;该级别下读不加锁,写加排他锁,写锁在事务提交或回滚后释放锁。读未提交可能会造成逻辑上一致性的问题;比如,可能读到其他事务还没提交的数据,也就是读到其他事务的中间状态。
(2)READ COMMITTED。读已提交;这是大部分数据库采用的隔离级别。从该级别后支持 MVCC (多版本并发控制),也就是提供一致性非锁定读;此时读取操作读取历史快照数据。该隔离级别下读取历史版本的最新数据,所以读取的是已提交的数据。这种隔离级别有可能存在一个问题:两个事务,一个事务有两个select读取同一行数据,另一个事务在两个select之间修改该行数据并提交,这就造成两次读的数据不一致。

(3)REPEATABLE READ。可重复读(RR);该级别下也支持 MVCC,此时读取操作读取事务开始时的版本数据。这个隔离级别可以解决READ COMMITTED逻辑上的问题,避免了两次读取的数据不一致。这个也存在一个逻辑问题,就是如果是两次范围读取数据,而第二次读取数据使用了for update(加锁),就会造成两次读的行记录不一样,即幻读。

(4)SERIALIZABLE。可串行化;该级别下给读加了共享锁;所以事务都是串行化的执行,此时隔离级别最严苛。(这个隔离级别下解决数据的逻辑一致性问题,但是性能很差)
相关命令:
-- 设置隔离级别
SET [GLOBAL | SESSION] TRANSACTION ISOLATION
LEVEL REPEATABLE READ;
-- 或者采用下面的方式设置隔离级别
SET @@tx_isolation = 'REPEATABLE READ';
SET @@global.tx_isolation = 'REPEATABLE READ';
-- 查看全局隔离级别
SELECT @@global.tx_isolation;
-- 查看当前会话隔离级别
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
-- 手动给读加 S 锁
SELECT ... LOCK IN SHARE MODE;
-- 手动给读加 X 锁
SELECT ... FOR UPDATE;
-- 查看当前锁信息
SELECT * FROM information_schema.innodb_locks;
不同隔离级别并发异常
准备工作,建立一张数据表:
DROP TABLE IF EXISTS `account_t`;
CREATE TABLE `account_t`(`id` int(11) not NULL,`name` VARCHAR(255) DEFAULT NULL,`money` INT(11) DEFAULT 0,PRIMARY KEY (`id`),KEY `idx_name` (`name`)
)ENGINE=INNODB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;select * from `account_t`;
INSERT into `account_t` values(1,'c',1000),(2,'b',1000),(3,'a',1000);
脏读
一个事务读到另一个未提交事务修改的数据。事务(A)可以读到另外一个事务(B)中未提交的数据;也就是事务A读到脏数据。
-- 事务2
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;BEGIN
-- 先执行查询
select money from `account_t` WHERE name='a';
-- 事务1更改数据后,再次执行查询
select money from `account_t` WHERE name='a';ROLLBACK;-- 事务1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;BEGIN
-- 事务2先执行查询,再修改数据
UPDATE `account_t` set money=money-100 WHERE name='a';UPDATE `account_t` set money=money+100 WHERE name='b';COMMIT;
ROLLBACK;

在读写分离的场景下,可以将 slave 节点设置为 READ UNCOMMITTED;此时脏读不影响,在 slave 上查询并不需要特别精准的返回值。
不可重复读
事务(A) 可以读到另外一个事务(B)中提交的数据;通常发生在一个事务中两次读到的数据是不一样的情况;不可重复读在隔离级别 READ COMMITTED 存在。
一般而言,不可重复读的问题是可以接受的,因为读到已经提交的数据,一般不会带来很大的问题,所以很多厂商(如Oracle、SQL Server)默认隔离级别就是 READ COMMITTED。
-- 事务1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGINUPDATE `account_t` set money=money-100 WHERE name='a';UPDATE `account_t` set money=money+100 WHERE name='b';COMMIT;-- 事务2
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGIN
-- 事务1更新数据并提交前执行
select money from `account_t` WHERE name='a';
-- 事务1更新数据并提交后 执行
select money from `account_t` WHERE name='a';
COMMIT;

幻读
两次读取同一个范围内的记录得到的结果集不一样。
例如:

幻读在隔离级别 REPEATABLE READ 及以下存在;但是可以在 REPEATABLE READ 级别下通过读加锁(使用 next-key locking)解决(即把上图中步骤3改成步骤5的语句)。
区别
(1)脏读和不可重复读的区别在于,脏读是读取了另一个事务未提交的数据,而不可重复读是读取了另一个事务提交后的修改。本质上都是其他事务的修改影响了本事务的读取。
(2)不可重复读和幻读比较类似;不可重复读是两次读取同一条记录,得到不一样的结果;而幻读是两次读取同一个范围内的记录得到的结果集不一样(可能不同个数,也可能相同个数内容不一样,比如x一行后又添加新行)。
(3)不可重复读是因为其他事务进行了 update 操作,幻读是因为其他事务进行了 insert或者 delete 操作。

总结
- redolog在事务提交后,记录DML操作对应物理页修改的内容。
- undolog记录DML操作步骤,用于回滚(通过逆运算回滚);undolog记录了事务的操作步骤以及历史版本信息。
- 在innodb中,一条SQL语句也是一个事务,是一个单独的事务,不需要begin… commit。
- 脏读是一个事务读取到另一个未提交事务修改的数据;不可重复的是一个事务内两次读取同一数据不一样。
- 幻读是一个事务内两次读取同一范围内的记录得到的结果集不一样。
- 不可重复读和幻读比较类似;不可重复读是两次读取同一条记录,得到不一样的结果;而幻读是两次读取同一个范围内的记录得到的结果集不一样。
- 重点掌握脏读、不可重复读、幻读的区别。
相关文章:
第26章_事务概述与隔离级别
文章目录 事务事务的特征事务的控制语句事务的生命周期事务的执行过程 ACID特性原子性一致性隔离性持久性 隔离级别不同隔离级别并发异常脏读不可重复读幻读区别 总结 事务 (1)事务的前提:并发连接访问。MySQL的事务就是将多条SQL语句作为整…...
合肥工业大学网络安全实验IP-Table
✅作者简介:CSDN内容合伙人、信息安全专业在校大学生🏆 🔥系列专栏 :hfut实验课设 📃新人博主 :欢迎点赞收藏关注,会回访! 💬舞台再大,你不上台,永远是个观众。平台再好,你不参与,永远是局外人。能力再大,你不行动,只能看别人成功!没有人会关心你付出过多少…...
Docker本地镜像发布到阿里云或私有库
本地镜像发布到阿里云流程 : 1.自己生成个要传的镜像 2.将本地镜像推送到阿里云: 阿里云开发者平台:开放云原生应用-云原生(Cloud Native)-云原生介绍 - 阿里云 2.1.创建仓库镜像: 2.1.1 选择控制台,进入容器镜像服…...
使用openvc进行人脸检测:Haar级联分类器
1 人脸检测介绍 1.1 什么是人脸检测 人脸检测的目标是确定图像或视频中是否存在人脸。如果存在多个面,则每个面都被一个边界框包围,因此我们知道这些面的位置 人脸检测算法的主要目标是准确有效地确定图像或视频中人脸的存在和位置。这些算法分析数据…...
Netty心跳检测
文章目录 一、网络连接假死现象二、服务器端的空闲检测三、客户端的心跳报文 客户端的心跳检测对于任何长连接的应用来说,都是一个非常基础的功能。要理解心跳的重要性,首先需要从网络连接假死的现象说起。 一、网络连接假死现象 什么是连接假死呢&…...
【leaflet】1. 初见
▒ 目录 ▒ 🛫 导读需求开发环境 1️⃣ 概念概念解释特点 2️⃣ 学习路线图3️⃣ html示例🛬 文章小结📖 参考资料 🛫 导读 需求 要做游戏地图了,看到大量产品都使用的leaflet,所以开始学习这个。 开发环境…...
数据结构与算法(Java版) | 详解十大经典排序算法之一:冒泡排序
前面虽然大家已经知道了多种不同的排序算法,但是我一直都没来得及给大家讲,所以,从这一讲起,我就要开始来给大家详细讲解具体的这些排序算法了。 下面,我们先来看第一个最常见的排序,即冒泡排序。 冒泡排…...
轻量封装WebGPU渲染系统示例<24>- Rendering Pass Graph基本用法(源码)
当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/feature/rendering/src/voxgpu/sample/PassNodeGraphTest.ts 此示例基于此渲染系统实现,当前示例TypeScript源码如下: class PassGraph extends WGRPassNodeGraph {constructor() { super();…...
开设自己的网站系类01购买服务器
开始建设自己的网站吧! 编者买了一个服务器打算自己构建一个网站,用于记录生活。网站大概算是一个个人博客吧。记录创建过程的一些步骤 要开设自己的网站,需要执行以下关键步骤 以下只是初步列出了建立自己的网站的大概步骤,后…...
FTP、NFS、SAMBA系统服务一
一、rsync托管xinetd 1、为什么要进行服务托管 独立服务:独立启动脚本 ssh ftp nfs dns ... 依赖服务: 没有独立的启动脚本 rsync telnet 依赖xinetd服务(独立服务) 2、如何将rsync托管给xinetd服务去管理? 第一步࿱…...
transfomer模型——简介,代码实现,重要模块解读,源码,官方
一、什么是transfomer Transformer是一种基于注意力机制(attention mechanism)的神经网络架构,最初由Vaswani等人在论文《Attention Is All You Need》中提出。它在自然语言处理(NLP)领域取得了巨大成功,特…...
队列(Queue):先进先出(FIFO)的数据结构
队列是一种基本的数据结构,用于在计算机科学和编程中管理数据的存储和访问。队列遵循先进先出(First In, First Out,FIFO)原则,即最早入队的元素首先出队。这种数据结构模拟了物理世界中的队列,如排队等待服…...
吃透 Spring 系列—AOP部分
目录 ◆ AOP 简介 - AOP的概念 - AOP思想的实现方案 - 模拟AOP的基础代码 - AOP相关概念 ◆ 基于xml配置的AOP - xml方式AOP快速入门 - xml方式AOP配置详解 - xml方式AOP原理剖析 ◆ 基于注解配置的AOP - 注解方式AOP基本使用 - 注解方式AOP配置详解 - 注解…...
redis 问题解决 2
1.4 数据存储 1、Redis 的数据过期策略是什么? Redis的数据过期策略包括两种机制:被动删除和主动删除。 被动删除: 当某个键被访问时,如果发现这个键已经过期,Redis会立即删除这个键。这意味着如果一个过期的键从未被访问,它就不会被自动删除。这是一种惰性删除策略。主…...
Spring Boot 校验用户上传的图片文件
图片上传是现代应用中非常常见的一种功能,也是风险比较高的一个地方。恶意用户可能会上传一些病毒、木马。这些东西不仅严重威胁服务器的安全还浪费了带宽,磁盘等资源。所以,在图片上传的接口中,一定要对用户上传的文件进行严格的…...
【springboot配置项动态刷新】与【yaml文件转换为java对象】
文章目录 一,序言二,准备工作1. pom.xml引入组件2. 配置文件示例 三,自定义配置项动态刷新编码实现1. 定义自定义配置项对象2. 添加注解实现启动时自动注入3. 实现yml文件监听以及文件变化处理 四,yaml文件转换为java对象1. 无法使…...
JS移动端触屏事件
在我们PC端中有许多的事件,那我们在移动端有没有事件呢?让我为大家介绍一下移动端常用的事件,触屏事件 触屏事件 touch (也称触摸事件),Android 和IOS 都有 touch 对象代表一个触摸点。触摸点可能是一根手指,也可能是一…...
C语言——打印1000年到2000年之间的闰年
闰年: 1、能被4整除不能被100整除 2、能被400整除 #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int year;for(year 1000; year < 2000; year){if((year%4 0) && (year%100!0) || (year%400 0)){printf("%d ",ye…...
【Linux】【驱动】设备树下的paltform总线
【Linux】【驱动】设备树下的paltform总线 1. 驱动程序的完整代码2. 使用到的相关函数3 使用到的指令3.2 设备上使用的指令 1. 驱动程序的完整代码 主要是展示了通过总线上挂载的方式来实现相关的数据读取 实质上就是几个of函数的调用。 /** Author: topeet* Description: 设…...
洛谷 NOIP 2023 模拟赛-汪了个汪-题解
简要题意 棋盘上有 n n n 行,第 i i i 行有 i i i 个格子。你要在格子填 1 ∼ n 1\sim n 1∼n,满足: 每行第一个数互不相同所有在行上相邻的两个数所组成的无序对互不相同每行的数互不相同 n ≤ 4000 n\le4000 n≤4000 题解 容易发现…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文通过代码驱动的方式,系统讲解PyTorch核心概念和实战技巧,涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...
