MySQL事务详解

MySQL事务详解

    • 数据库事务概述
      • 事务是如何实现的
      • 事务的ACID特性
      • 事务的状态
    • 事务的使用
      • 显式事务
      • 隐式事务
      • 示例
        • 自动提交
        • 回滚
        • 回滚到保存点
    • 事务的隔离级别
      • 数据并发问题
      • MySQL 支持的四种隔离级别
      • 注意
        • 示例
      • 设置隔离级别
    • 事务的常见分类

数据库事务概述

数据库事务是数据库管理系统(DBMS)中的一个关键概念,它涉及到一系列数据库操作,这些操作要么全部执行成功,要么全部不执行,以保持数据库的一致性。事务是确保数据库数据完整性和可靠性的基础。

事务是如何实现的

事务就是一组逻辑操作的集合。实现事务就是要保证可靠性和并发隔离,或者说,能够满足ACID特性的机制。而这些主要是靠日志恢复和并发控制实现的。

  • 日志恢复:数据库里有两个日志,一个是redo log,一个是undo log。redo log记录的是已经成功提交的事务操作信息,用来恢复数据,保证事务的持久性。undo log记录的是事务修改之前的数据信息,用来回滚数据,保证事务的原子性
  • 并发控制:并发控制主要靠锁机制和MVCC(多版本并发控制)来实现,保证事务的隔离性
  • 一致性则是通过持久性+原子性+隔离性来保证。

事务的ACID特性

  • 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,要么全部提交,要么全部失败回滚,没有中间状态。

  • 一致性(Consistency): 事务开始前和结束后,数据库从一个合法的状态转移到另一个合法的状态,即便在事务执行的过程中发生了错误或异常,也要保证数据库的完整性和业务规则没有被破坏。

  • 隔离性(Isolation): 多个事务并发执行时,每个事务的操作应该与其他事务隔离,不互相影响。

  • 持久性(Durability): 一旦事务提交,对数据库的修改应该是永久的,即使发生系统故障也不会丢失。

事务的状态

  1. 活动(Active): 事务进入活动状态表示它已经开始,但尚未完成。这是事务的起始状态。
  2. 部分提交(Partially Committed): 事务执行了所有的SQL语句,但尚未提交。在这个状态下,事务对数据库所做的修改已被写入事务日志,但尚未应用到数据库中。
  3. 已提交(Committed): 事务已经成功完成并已提交。在这个状态下,事务对数据库所做的修改已经永久保存在数据库中,成为数据库的一部分。
  4. 失败(Failed): 事务执行过程中发生了一个错误,导致事务无法继续执行。在这个状态下,通常会选择回滚事务,将数据库恢复到事务开始前的状态。
  5. 中止(Aborted): 事务被中止,可能是由于发生错误导致的回滚,也可能是由于应用程序显式地中止了事务。
  6. 挂起(Suspended): 事务处于一个暂时的挂起状态,等待某些条件满足后再继续执行。这通常与事务隔离级别相关,例如,在并发控制中等待其他事务释放锁。

这些状态反映了事务在其生命周期内可能经历的不同阶段。MySQL通过事务日志(transaction log)和锁来跟踪和管理事务的状态,以确保事务的ACID属性得到维护。了解事务的不同状态是非常重要的,以便在处理错误、调优性能或者确保数据一致性时能够采取适当的操作。

事务的使用

事务的完成过程:

  • 开启事务
  • 一系列 DML 操作
  • 结束事务

使用事务有两种方式,分别为 显式事务 和 隐式事务 。

显式事务(Explicit Transaction):

  • 手动启动: 明确地使用 START TRANSACTION 或者 BEGIN 语句来显式地启动一个事务。这表示从这一点开始,所有的数据库操作将作为一个事务进行处理。
  • 手动提交或回滚: 在事务执行结束后,需要明确地使用 COMMIT 提交事务,或者使用 ROLLBACK 回滚事务。这使得开发者有更精确的控制,可以根据业务逻辑决定是否提交或回滚事务。

隐式事务(Implicit Transaction):

  • 自动启动: 在默认情况下,每个SQL语句都被视为一个事务。这意味着在执行SQL语句时,会自动启动一个事务。
  • 自动提交: 在隐式事务中,每个SQL语句执行后都会自动提交事务,除非显式地使用 SET AUTOCOMMIT=0 关闭自动提交,这时需要使用 COMMITROLLBACK 手动处理事务。

显式事务

1.开启事务

使用START TRANSACTION 或者 BEGIN 开启一个事务。

START TRANSACTION;
BEGIN;

START TRANSACTION 语句相较于 BEGIN 特别之处在于,后边能跟随几个 修饰符 :

  • READ ONLY :标识当前事务是一个 只读事务 ,也就是属于该事务的数据库操作只能读取数据,而不 能修改数据。

  • READ WRITE :标识当前事务是一个 读写事务 ,也就是属于该事务的数据库操作既可以读取数据, 也可以修改数据。

  • WITH CONSISTENT SNAPSHOT :启动一致性读。

2.一系列事务中的操作

主要是DML(增删改查),不含DDL。

3.提交事务或者中止事务

# 提交事务。当提交事务后,对数据库的修改是永久性的。
COMMIT;
# 回滚事务。即撤销正在进行的所有没有提交的修改 
ROLLBACK;
# 将事务回滚到某个保存点。
ROLLBACK TO [SAVEPOINT]

保存点

# 创建保存点
SAVEPOINT 保存点名称;
# 删除保存点
RELEASE SAVEPOINT 保存点名称;

隐式事务

MySQL中有一个系统变量 autocommit :默认是ON,也就是开启自动事务。

在这里插入图片描述

关闭自动提交:

  • 显式的的使用 START TRANSACTION 或者 BEGIN 语句开启一个事务。这样在本次事务提交或者回 滚前会暂时关闭掉自动提交的功能。
  • 把系统变量autocommit的值设置为 OFF ,就像这样:
SET autocommit = OFF;
#或
SET autocommit = 0;

示例

自动提交

MySQL 默认开启自动提交,每条语句都是一个事务。

在这里插入图片描述

关闭自动提交后,可以多条语句为一个事务。

在这里插入图片描述

回滚

开启事务,插入一条新数据。

在这里插入图片描述

在这里插入图片描述

回滚,回滚后数据回到开启事务前的状态。

在这里插入图片描述

回滚到保存点

开启事务,插入数据,设置保存点

在这里插入图片描述

回滚到保存点

在这里插入图片描述

需要注意的是,回滚到保存点并不是事务的终止状态,所以不会提交事务

在这里插入图片描述

事务的隔离级别

数据并发问题

脏读:指一个事务读取到了另一个事务修改但是还没有提交的数据,如果另一个事务后来回滚了,读取到的数据就是无效的,导致事务读取到的数据是“脏”的,因为它基于未提交的数据。

比如A向B转账100,A的账户减少了100,而B的账户还没来得及修改,此时一个并发的事务访问到了B的账户,就是脏读

不可重复读:指一个事务多次读取同一条记录,但前后读到的数据不一致。因为当前事务在读取记录的间隙中,其他事务在此期间修改或删除了数据并进行了提交, 这可能导致事务在执行期间看到不一致的数据,破坏了事务的一致性。

比如A第一次查询自己的账户有100元,此时另一个事务给A的账户增加了100元,所以A再次读取他的账户得到了200的结果,跟第一次读取的不一样。

不可重复读与脏读的不同之处在于,脏读是读取了另一个事务没有提交的脏数据,不可重复读是读取了已经提交的数据,实际上并不是一个异常现象。

幻读:事务在查询特定记录的总数时,前后查询的结果不一致。这是由于在事务查询间隙时,在此期间插入了新的数据。 这可能导致事务在执行期间看到不一致的数据,破坏了事务的一致性。

比如A公司一共有100个人,第一次查询总人数得到100条记录,此时另一个事务新增了一个人,所以下一次查询得到101条记录。
不可重复度和幻读的不同之处在于,幻读是多次读取的结果行数不同,不可重复度是读取结果的值不同。

MySQL 支持的四种隔离级别

READ UNCOMMITTED :读未提交,在该隔离级别,所有事务都可以看到其他未提交事务的执行结 果。不能避免脏读、不可重复读、幻读。

READ COMMITTED :读已提交,它满足了隔离的简单定义:一个事务只能看见已经提交事务所做 的改变。这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。可以避免脏读,但不可 重复读、幻读问题仍然存在。

REPEATABLE READ :可重复读,事务A在读到一条数据之后,此时事务B对该数据进行了修改并提 交,那么事务A再读该数据,读到的还是原来的内容。可以避免脏读、不可重复读,但幻读问题仍 然存在。这是MySQL的默认隔离级别。

SERIALIZABLE :可串行化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止 其他事务对该表执行插入、更新和删除操作。所有的并发问题都可以避免,但性能十分低下。能避 免脏读、不可重复读和幻读。

这四种隔离级别具体是如何实现的呢?

  • 对于「读未提交」隔离级别的事务来说,因为可以读到未提交事务修改的数据,所以直接读取最新的数据就好了;
  • 对于「串行化」隔离级别的事务来说,通过加读写锁的方式来避免并行访问;
  • 对于「读提交」和「可重复读」隔离级别的事务来说,它们是通过 Read View 来实现的,它们的区别在于创建 Read View 的时机不同,大家可以把 Read View 理解成一个数据快照,就像相机拍照那样,定格某一时刻的风景。「读提交」隔离级别是在「每个语句执行前」都会重新生成一个 Read View,而「可重复读」隔离级别是「启动事务时」生成一个 Read View,然后整个事务期间都在用这个 Read View

注意

MySQL 虽然支持 4 种隔离级别,但是与SQL 标准中规定的各级隔离级别允许发生的现象却有些出入。

MySQL 在「可重复读」隔离级别下,可以很大程度上避免幻读现象的发生(注意是很大程度避免,并不是彻底避免),所以 MySQL 并不会使用「串行化」隔离级别来避免幻读现象的发生,因为使用「串行化」隔离级别会影响性能。

MySQL InnoDB 引擎的可重复读隔离级别(默认隔离级),根据不同的查询方式,分别提出了避免幻读的方案:

  • 针对快照读(普通 select 语句),是通过 MVCC 方式解决了幻读,因为可重复读隔离级别下,事务执行过程中看到的数据,一直跟这个事务启动时看到的数据是一致的,即使中途有其他事务插入了一条数据,是查询不出来这条数据的,所以就很好了避免幻读问题。
  • 针对当前读(select … for update 等语句),是通过 next-key lock(记录锁+间隙锁)方式解决了幻读,因为当执行 select … for update 语句的时候,会加上 next-key lock,如果有其他事务在 next-key lock 锁范围内插入了一条记录,那么这个插入语句就会被阻塞,无法成功插入,所以就很好了避免幻读问题。
示例

其他事务增加数据后,当前事务的查询结果并不会改变。

在这里插入图片描述

但是,虽然当前事务查询不到,但是能够修改且修改后就能查询到。

在这里插入图片描述

所以MySQL 在「可重复读」隔离级别下,可以很大程度上避免幻读现象的发生但不能彻底避免。

设置隔离级别

查看默认隔离级别

SELECT @@transaction_isolation;

设置隔离级别

SET [GLOBAL|SESSION] TRANSACTION ISOLATION LEVEL 隔离级别;
#其中,隔离级别格式:
> READ UNCOMMITTED
> READ COMMITTED
> REPEATABLE READ
> SERIALIZABLE
SET [GLOBAL|SESSION] TRANSACTION_ISOLATION = '隔离级别'
#其中,隔离级别格式:
> READ-UNCOMMITTED
> READ-COMMITTED
> REPEATABLE-READ
> SERIALIZABLE
# SET SESSION TRANSACTION_ISOLATION = '隔离级别' == SET TRANSACTION_ISOLATION = '隔离级别'

关于设置时使用GLOBAL或SESSION的影响:(默认 SESSION )

  • 使用 GLOBAL 关键字(在全局范围影响):
    • 当前已经存在的会话无效
    • 只对执行完该语句之后产生的会话起作用
  • 使用 SESSION 关键字(在会话范围影响):
    • 对当前会话的所有后续的事务有效
    • 如果在事务之间执行,则对后续的事务有效
    • 该语句可以在已经开启的事务中间执行,但不会影响当前正在执行的事务

事务的常见分类

  1. 扁平事务(Flat Transactions):
    • 扁平事务指整个应用中的所有操作都在一个事务内执行。事务在应用的整个执行过程中始终存在,直到应用执行完成或者发生错误。
  2. 带有保存点的扁平事务(Flat Transactions with Savepoints):
    • 这是扁平事务的扩展,其中引入了保存点(Savepoints)。保存点允许在事务中创建一个标记,使得事务可以回滚到这个标记处,而不必回滚整个事务。这在处理部分错误时可以更灵活地回滚事务的一部分。
  3. 链事务(Chained Transactions):
    • 链事务是一种序列化的事务执行方式,其中一个事务的提交触发另一个事务的开始。每个事务在前一个事务成功提交后才能开始执行。这样可以确保事务按照定义的顺序执行。
  4. 嵌套事务(Nested Transactions):
    • 嵌套事务是指事务内可以包含另一个事务。在这种情况下,内部事务的提交或回滚并不会立即影响外部事务,而是在外部事务提交时才会生效。大多数数据库系统不直接支持真正的嵌套事务,但是可以通过保存点(Savepoints)来模拟。
  5. 分布式事务(Distributed Transactions):
    • 分布式事务涉及多个独立的事务性资源管理器,如数据库、消息队列等。在分布式系统中,确保所有相关资源的事务要么全部提交,要么全部回滚是具有挑战性的。分布式事务通常需要协调者(coordinator)和参与者(participants)之间的通信和协调,以确保一致性和隔离性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/186225.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《山水间的家》第二季收官,国台酒业解锁中国式浪漫

执笔 | 洪大大 编辑 | 萧 萧 近日,由国台酒特别支持的大型文旅探访节目《山水间的家》第二季在总台央视综合频道(CCTV-1)正式收官。 第二季节目以家庭为视角切入,先后走进江苏、四川、重庆、江西、湖北、贵州、浙江等地24个特色…

Redis安装和部署详细流程

文章目录 一、Windows环境下安装 Redis1.1 下载Redis1.2 启动redis服务器1.3 启动redis客户端1.4 配置环境变量 参考资料 一、Windows环境下安装 Redis windows系统环境下,redis安装方式主要有: zip压缩包方式 https://redis.io/download 或者 https:/…

MMdetection3.0 问题

MMdetection3.0 问题 希望各位路过的大佬指教一下: 问题: 1、NWPU-VHR-10有标注的数据一共650张,我将其分为了455张训练集,195张验证集。 2、然后使用MMdetection3.0框架中的Faster-rcnn网络进行训练,设置训练参数b…

CityEngine2023 根据shp数据构建三维模型并导入UE5

目录 0 引言1 基本操作2 实践2.1 导入数据(.shp)2.2 构建三维模型2.3 将模型导入UE5 🙋‍♂️ 作者:海码007📜 专栏:CityEngine专栏💥 标题:CityEngine2023 根据shp数据构建三维模型…

Android问题笔记四十九:ViewPager 嵌套 Fragment 扩大滑动响应区域,避免左右滑动过于灵敏问题

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC 👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分…

finebi 新手入门案例

finebi 新手入门案例 连锁超市销售数据分析 步骤: 准备公共数据新建分析主题处理数据在数据中分析在图形中分析数据大屏 准备公共数据 点击公共数据 点击新建文件夹 修改文件夹名称 上传数据 鼠标悬停在文件夹上,右侧出现 鼠标悬停在文件夹上&#x…

git-5

1.GitHub为什么会火? 2.GitHub都有哪些核心功能? 3.怎么快速淘到感兴趣的开源项目 github上面开源项目非常多,为了我们高效率的找到我们想要的资源 根据时间 不进行登录,是没有办法享受到高级搜索中的代码功能的,登录…

maven 基础

maven常用命令 clean &#xff1a;清理 compile&#xff1a;编译 test&#xff1a;测试 package&#xff1a;打包 install&#xff1a;安装 maven坐标书写规范 <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</ar…

从功能测试到自动化测试,我总结了一些工作经验分享给大家

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

python高级练习题库实验1(A)部分

文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目总结题目1 输入一个整数,用于控制输出*的个数,输入日期,按照特定格式输出 研究下面的例子,并编写一个与这些例子完全相同的程序。 代码 import datetime# ask user for length of b…

咨询+低代码,强强联合为制造业客户赋能

内容来自演讲&#xff1a;沈毅 | 遨睿智库 | 董事长 & 王劭禹 | 橙木智能 | 联合创始人 摘要 文章主要讲述了智库董事长沈毅创办广告公司的经历&#xff0c;以及他在管理公司过程中遇到的问题和挑战&#xff0c;最后通过与明道云以及橙木智能联合创始人王邵禹老师的合作&…

【驱动】SPI驱动分析(四)-关键API解析

关键API 设备树 设备树解析 我们以Firefly 的SPI demo 分析下dts中对spi的描述&#xff1a; /* Firefly SPI demo */ &spi1 {spi_demo: spi-demo00{status "okay";compatible "firefly,rk3399-spi";reg <0x00>;spi-max-frequency <48…

【C++ Primer Plus学习记录】循环和文本输入

目录 1.使用原始的cin进行输入 2.使用cin.get(char)进行补救 3.使用哪一个cin.get() 4.文件尾条件 循环完后的一项最常见、最重要的任务&#xff1a;逐字符地读取来自文件或键盘的文本。 cin对象支持3种不同模式的单字符输入&#xff0c;其用户接口各不相同。下面介绍如何…

鸿蒙HarmonyOS应用开发-ColumnRow组件

1 概述 一个丰富的页面需要很多组件组成&#xff0c;那么&#xff0c;我们如何才能让这些组件有条不紊地在页面上布局呢&#xff1f;这就需要借助容器组件来实现。 容器组件是一种比较特殊的组件&#xff0c;它可以包含其他的组件&#xff0c;而且按照一定的规律布局&#xf…

UE5富文本框学习(用途:A(名字)用刀(图片)击杀B(名字))

UE5-UMG教程-通用控件&#xff1a;多格式文本块&#xff08;RichTextBlock&#xff09;_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Pu4y1k7Z2/?p54&spm_id_frompageDriver 结果示例&#xff1a; 1.添加富文本框 2.添加文字样式库 点添加&#xff0c;更改每行行…

Embedding压缩之hash embedding

在之前的两篇文章 CTR特征重要性建模&#xff1a;FiBiNet&FiBiNet模型、CTR特征建模&#xff1a;ContextNet & MaskNet中&#xff0c;阐述了特征建模的重要性&#xff0c;并且介绍了一些微博在特征建模方面的研究实践&#xff0c;再次以下面这张图引出今天的主题&#…

Unity 一些常用注解

在Unity中有一些比较常用的注解&#xff1a; 1、[SerializeField]&#xff1a;将私有字段或属性显示在 Unity 编辑器中&#xff0c;使其可以在 Inspector 窗口中进行编辑。 2、[Range(min, max)]&#xff1a;限制数值字段或属性的范围&#xff0c;在 Inspector 窗口中以滑动条…

简单好用!日常写给 ChatGPT 的几个提示词技巧

ChatGPT 很强&#xff0c;但是有时候又显得很蠢&#xff0c;下面是使用 GPT4 的一个实例&#xff1a; 技巧一&#xff1a;三重冒号 """ 引用内容使用三重冒号 """&#xff0c;让 ChatGPT 清晰引用的内容&#xff1a; 技巧二&#xff1a;角色设定…

【C++】string模拟

string讲解&#xff1a;【C】String类-CSDN博客 基本框架 #pragma once #include <iostream> using namespace std; ​ namespace wzf {class string{public:// 默认构造函数string(): _str(new char[1]), _size(0), _capacity(0){_str[0] \0; // 在没有内容时仍要有终…

计算机体系结构----基本概念(一)

本文仅供学习&#xff0c;不作任何商业用途&#xff0c;严禁转载。绝大部分资料来自----计算机系统结构教程(第二版)张晨曦等 计算机体系结构----基本概念 计算机系统设计的定量原理1. Amdahl定律&#xff08;阿姆达尔定律&#xff09;2. CPU性能公式3. 程序的局部性原理 计算…