【Hello mysql】 mysql的事务

2023-11-19

Mysql专栏:@Mysql
本篇博客简介:介绍mysql的事务

事务的概念

事务就是一组DML语句组成,这些语句在逻辑上存在相关性,这一组DML语句要么全部成功,要么全部失败,是一个整体。MySQL提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。
事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。假设一种场景:你毕业了,学校的教务系统后台 MySQL 中,不在需要你的数据,要删除你的所有信息(一般不会:) ), 那么要删除你的基本信息(姓名,电话,籍贯等)的同时,也删除和你有关的其他信息,比如:你的各科成绩,你在校表现,甚至你在论坛发过的文章等。这样,就需要多条 MySQL 语句构成,那么所有这些操作合起来,就构成了一个事务。
正如我们上面所说,一个 MySQL 数据库,可不止你一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,在向 MySQL 服务器发起事务处理请求。而每条事务至少一条 SQL ,最多很多 SQL ,这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。甚至,因为事务由多条 SQL 构成,那么,也会存在执行到一半出错或者不想再执行的情况,那么已经执行的怎么办呢?

这个时候我们是不是应该就回滚到没有执行时的状态

事务的四个属性

所有,一个完整的事务,绝对不是简单的 sql 集合,还需要满足如下四个属性:

  • 原子性:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性:在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 隔离性:数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Readuncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化( Serializable )
  • 持久性:事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

上面四个属性,可以简称为 ACID 。

  • 原子性(Atomicity,或称不可分割性)
  • 一致性(Consistency)
  • 隔离性(Isolation,又称独立性)
  • 持久性(Durability)

事务的作用

事务被 MySQL 编写者设计出来,本质是为了当应用程序访问数据库的时候,事务能够简化我们的编程模型,不需要我们去考虑各种各样的潜在错误和并发问题.可以想一下当我们使用事务时,要么提交,要么回滚,我们不会去考虑网络异常了,服务器宕机了,同时更改一个数据怎么办对吧?因此事务本质上是为了应用层服务的.而不是伴随着数据库系统天生就有的.

支持事务的引擎

我们可以通过 show engines 指令来查看支持事务的引擎
在这里插入图片描述

可以看到的是 在mysql中 只有innodb支持事务

事务的提交方式

事务的提交方式常见的有以下两种

  • 自动提交
  • 手动提交

我们使用 show variables like ‘autocommit’ 可以查看默认的事务提交方式

在这里插入图片描述

此外我们可以使用set指令来改变事务的提交方式

当我们将autocommit设置为0的时候自动提交关闭 设置为1的时候自动提交开启

在这里插入图片描述

事务功能测试

(第一次看到下面这些专业名词的时候 一些读者可能会一脸懵 不知道在说什么 但是看完整篇博客之后再回过来看就会理解了)

读–未提交测试

首先我们要设置以下事务的隔离级别 设置语法如下

set global translation isolation level read uncommitted;

退出mysql重新登录之后我们可以使用 select @@tx_isolation 指令来查看隔离级别

在这里插入图片描述

演示一: 事务的开始 回滚 提交

首先我们需要创建一个测试表

在这里插入图片描述

此时我们创建两个mysql客户端 一个开始运行事务 一个负责查看变化

事务启动的命令是 begin

在这里插入图片描述

我们发现 在一个客户端事务中进行的所有数据都能够被另一个客户端所看到

此时我们在这里设置一个回滚点 之后插入一个新的数据

在这里插入图片描述

如果我们觉得这个数据不需要 还想要上面的一个版本 那么直接回滚到上个回滚点就好

在这里插入图片描述
当然 如果想回滚到事务刚开始的状态则直接使用rollback指令即可

在这里插入图片描述

演示二:开启事务后客户端崩溃

在这里插入图片描述

之后我们左边开始向account表中插入事务

在这里插入图片描述

插入数据之后我们可以发现右边的客户端也可以看到数据

之后我们使用信号让左边客户端强制中断 之后再次用右边的客户端查看数据
在这里插入图片描述

我们可以发现 account表中的数据不见了 这个现象实际上说明了三点

  1. 事务是原子性的 要么完成 要么未完成 没有中间状态
  2. 如果一个事务在运行的过程中被终端了 那么它会回滚到最开始的版本
  3. 自动提交和手动开启的事务没有关系

演示三: 单条sql语句和事务的关系

首先我们将自动提交关闭
在这里插入图片描述

之后使用单条sql语句向account表中插入数据 并在另一个客户端查看

在这里插入图片描述

此时我们发现 就算我们没有开启事务 使用单条sql语句插入之后中断客户端 数据也会进行回滚 这是为什么呢?

其实我们的单条sql语句也是一个事务 只不过我们之前开启了自动提交 所以说每次执行完单条sql语句之后数据就自动提交并且持久化

而当我们关闭自动提交之后 如果没有手动commit而中断客户端 那么mysql就认为这是一个未完成的事务而直接回退到一开始的版本中了

事务的隔离级别

如何理解隔离性(粗浅理解)

  • MySQL服务可能会同时被多个客户端进程(线程)访问,访问的方式以事务方式进行
  • 一个事务可能由多条SQL构成,也就意味着,任何一个事务,都有执行前,执行中,执行后的阶段。而所谓的原子性,其实就是让用户层,要么看到执行前,要么看到执行后。执行中出现问题,可以随时回滚。所以单个事务,对用户表现出来的特性,就是原子性。
  • 但毕竟所有事务都要有个执行过程,那么在多个事务各自执行多个SQL的时候,就还是有可能会出现互相影响的情况。比如:多个事务同时访问同一张表,甚至同一行数据。
  • 数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性
  • 数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

隔离级别

一共有四种隔离级别

  • 读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等,我们上面为了做实验方便,用的就是这个隔离性。
  • 读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果。
  • 可重复读【Repeatable Read】: 这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题。(mysql中解决了这个问题)
  • 串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决了幻读的问题。它在每个读的数据行上面加上共享锁。但是可能会导致超时和锁竞争(这种隔离级别太极端,实际生产基本不使用)

为什么要有隔离级别

隔离级别实际上就是在效率和安全之间找到一个平衡点

而mysql之所以设置这么多隔离级别就是为了让用户有得选

脏读 幻读 不可重复读是什么意思

脏读: 一个事务在执行过程中读到了其他事务没有提交的数据

我们在上面的实验中肯定知道了一点 如果一个事务没有提交 那么它的数据是不一定会留下来的

那么我们读取了一个可能不会存在的数据 这肯定是一个问题

幻读: 一个事务在执行过程中读取了通过select读取了新的数据

一般来说我们加锁针对的是已存在的数据 所以说加锁之后 删改查 并不会有什么问题 但是对于不存在的数据我们无法加锁 也就是说我们无法保证是否有事务向数据库表中插入新的数据 如果说我们前后的select不一致(强调后面的select读取出了新的数据) 那么这个时候就是出现了幻读问题

mysql通过Next-Key锁(GAP+行锁)的形式解决了在可重复度隔离级别下的幻读问题

不可重复读: 一个事务在执行过程中多次读取的数据不一致的

这个问题主要出现在读提交隔离级别中 我们每次读取的时候都会受到别的事务提交数据的影响

查看和设置隔离级别

查看全局隔离级别

在这里插入图片描述

查看当前会话隔离级别

在这里插入图片描述

设置隔离级别

语法

--设置当前会话 or 全局隔离级别语法
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READCOMMITTED | REPEATABLE READ | SERIALIZABLE}

四种隔离级别详解

读 – 未提交

这是效率最高的一个隔离级别 也是安全性最差的一个隔离级别 平时我们不建议使用

下图两个客户端都被我们设置为了读–未提交隔离级别

在这里插入图片描述

之后我们让两个客户端同时查看一张表 一个客户端启动事务(不提交)向里面插入数据 一个客户端查看表

在这里插入图片描述

我们发现就算这个客户端没有提交数据 另外一个客户端还是能够看到数据 这个就是读未提交

读 - 提交

下图两个客户端都被我们设置为了读–提交隔离级别

在这里插入图片描述

之后我们左边客户端启动一个事务 并且插入一个数据之后 再使用右边的客户端查看数据 我们就会发现account数据表没有任何的变化

在这里插入图片描述

之后我们让右边的客户端开启一个事务 并且再次查询

在这里插入图片描述

之后左边commit 右边继续查询

在这里插入图片描述

我们发现当左边的客户端提交数据之后 右边再次查询读取了做百年新提交的数据 这也就造成了不可重复读的问题

可重复读

下面两个图中的客户端都被我们设置了可重复读隔离级别
在这里插入图片描述

之后我们同时启动两个事务

在这里插入图片描述

首先我们在右边的客户端中查询数据 之后让左边客户端插入数据之后提交 之后再次查看右边客户端的数据

在这里插入图片描述

我们发现此时右边客户端中的数据没有改变 还是一开始读取的那个 这就是可重复读

幻读问题

事实上我们刚刚的操作很可能会产生一个幻读问题 因为数据库只能对于存在的数据加锁 所以说插入的数据很可能会被再次select住

不过mysql通过Next-Key锁 (GAP+行锁)解决了这个问题 在使用其他数据库的时候我们仍然可能遇到

串行化

串行化是最安全 也是效率最低的一个模式

它直接暴力的将除了读以外的所有行为全部加锁 自然也就不会有安全上的问题了

这里就不作演示了

在这里插入图片描述

一致性的理解

一致性是由其他三个特性保证的 原因如下

  • 事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而改未完成的事务对数据库所做的修改已被写入数据库,此时数据库就处于一种不正确(不一致)的状态。因此一致性是通过原子性来保证的。
  • 事务处理结束之后必须要保证数据的保存是永久的 所以说一致性是通过持久性保证的
  • 在多个事务并行的时候 不会由于交叉执行而导致数据不一致 所以说一致性是通过隔离性保证的
  • 此外一致性还和用户的业务逻辑强相关 如果说用户的业务逻辑不正确就不能保证一致性

总结

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Hello mysql】 mysql的事务 的相关文章

  • android webview 函数 onPagefinished 被调用两次

    我的android webview功能onPageFinished被调用两次 我不知道为什么 但它在 android 2 2 上运行良好 但当我将其升级到 4 时 它就不起作用了 代码附在下面 Code Override public vo
  • 毕加索动画加载图像

    我有以下代码在毕加索中加载图像 使用可绘制的占位符在图像下载时显示 不过 我想要的是一个动画旋转进度条样式的旋转器 它可以在图像加载时不断地旋转 就像我在大多数专业应用程序中看到的那样 毕加索似乎不支持这一点 只支持静态图像可绘制 有没有办
  • 如何从一个代码库创建多个 Android 应用

    我有一个 Android 代码库 它使用带有设置的 API 来获取多个应用程序的不同数据 所有应用程序都使用相同的代码库 但进行一两个设计调整 那么如何重用主代码库而不必每次都复制整个 Android 项目呢 iPhone 在同一个项目中使
  • Android 应用被 Google Play 拒绝

    我最近向 Google Play 商店提交了一个 Android 应用程序 但收到一条消息说我的应用程序已被拒绝 我不确定问题是什么 也找不到确切的解决方案 拒绝原因 违反了禁止行为条款 内容政策 经过定期审核后 我们确定您的应用程序支持
  • Firestore - RecycleView - 图像持有者

    我不知道如何编写图像的支架 我已经设置了 2 个文本 但我不知道图像的支架应该是什么样子 你能帮我告诉我图像的文字应该是什么样子才能正确显示吗 holder artistImage setImageResource model getArt
  • 如何以编程方式断开拨出呼叫

    我使用以下代码以编程方式断开呼叫 但它不起作用 private void callDisconnect try TelephonyManager manager TelephonyManager this getSystemService
  • Android:应用内计费V3超时返回哪个响应码?

    出现网络超时情况时 Google Play 应用内结算服务 ice er V3 将返回哪些响应状态代码 它的所有功能都是统一的吗 我将在这里描述我的发现 我通过拔掉主机插头 在安装了全功能 GP GP Store V3 10 10 GP S
  • 应用内结算错误

    我的 UNMANAGED 应用内购买无法正常工作 在它完美运行之前 我可以使用测试帐户成功购买 但它突然不起作用了 因为我记得我对商家帐户所做的只是添加更多 2 4 个测试帐户 添加后 我的应用内购买将不起作用 所以我更新了公钥并上传了一个
  • 如何查看 Android 上的 Wi-Fi 是否已连接?

    我什至不希望我的用户尝试下载某些内容 除非他们连接了 Wi Fi 然而 我似乎只能判断是否启用了 Wi Fi 但他们仍然可以有 3G 连接 android net wifi WifiManager m WifiManager getSyst
  • 如何持续更新MPAndroidChart中的Y轴值

    我希望 LineChart 中的轴能够实时调整其最大值和最小值 当新数据的 Y 值增加 正值和负值 时 像 ResetAxisMaxValue 和 ResetAxisMinValue 这样的函数可以很好地工作 但是 一旦信号再次变低 Y 值
  • 导航抽屉默认片段

    我是一名新手开发人员 我正在将导航抽屉与 android support v7 集成到我的应用程序中 我有一个问题 当我启动应用程序时 主要布局是这样的
  • 如何在 Android NDK 中创建新的 NativeWindow 而无需 Android 操作系统源代码?

    我想编译一个 Android OpenGL 控制台应用程序 您可以直接从控制台启动 Android x86 运行 或者从 Android x86 GUI 内的 Android 终端应用程序运行 这个帖子 如何在 Android NDK 中创
  • Vimeo 视频在 Android 6 设备上停止播放

    我正在尝试在我的应用程序中播放 Vimeo 的视频 问题是在 Android 6 设备上 视频会在一定时间后停止播放 在 API 较低的设备上一切正常 时间取决于质量 对于下面提供的网址的视频 播放一定分钟 1 到 3 视频质量有多低 播放
  • Android - 如何更改 TimePicker 中的文本颜色?

    我正在使用 TimePicker 到 LinearLayout 中 背景颜色 黑色 但是 我看不到 TimePicker 中的数字 并且我需要在布局中将背景颜色设置为黑色 如何更改 TimePicker 中的 textColor 我已经尝试
  • 在Android Studio中更改项目主题?

    我使用浅色主题创建了一些项目 现在我想将其更改为深色 但我不知道该怎么做 顺便说一句 我不是问如何在代码中做到这一点 只是问如何更改项目的默认主题 在 AndroidManifest xml 的 application 标签下 您可以设置您
  • Android - 9 补丁

    我正在尝试使用 9 块图片创建一个新的微调器背景 我尝试了很多方法来获得完美的图像 但都失败了 s Here is my 9 patch 当我用Draw 9 patch模拟时 内容看起来不错 但是带有箭头的部分没有显示 或者当它显示时 这部
  • Android AutoCompleteTextView 带芯片

    我不确定我是否使用了正确的词语来描述此 UI 功能 但我已附上我希望在我的应用程序中实现的目标的快照 它由 Go SMS 使用 用户在编辑文本中键入联系人 在用户从完成下拉列表中选择联系人后 该联系人将被插入到编辑文本中 如附图所示 编辑文
  • 安卓的限制

    我需要构建一个应用程序 该应用程序拍摄相机图像并将其上传到网络 在网络上进行一些处理并返回真 假 我在这方面遇到了一些问题 希望得到澄清 1 我的应用程序有什么方法可以知道 Android 相机捕获的图像吗 我从这里明白了什么 Androi
  • 使用 PHP 将 latin1_swedish_ci 转换为 utf8

    我有一个数据库 里面充满了类似的值 Dhaka 应该是 Dhaka 因为我在创建数据库时没有指定排序规则 现在我想修复它 我无法从最初获取数据的地方再次获取数据 所以我在想是否可以在 php 脚本中获取数据并将其转换为正确的字符 我已将数据
  • 当ScrollView滚动到底部时加载更多数据

    我有一个带有动态加载内容的滚动视图 有时可能会有很多内容 所以我想在用户滚动到底部时加载更多内容 我搜索了合适的方法 发现了两种 onScrollChanged and getScrollY 但我不知道如何将它用于我的目的 请给我一些建议

随机推荐

  • centos7安装python3.x(多种方式)

    但行好事 莫问前程 有任何疑问请留言 作者有问必答哦 前言 centos系统本身默认安装有python2 x 版本x根据不同版本系统有所不同 可通过 python V 或 python version 查看系统自带的python版本 有一些
  • java POI在excel中插入等比例缩放的图片

    这个缩放的比例不是很准确 但还凑合能用 目前本人找不到其它方法 就先用这个 先看一个关键的API方法 void org apache poi ss usermodel Picture resize double scaleX double
  • DES加解密算法

    DES加解密算法 单密钥对称加解密算法 入口参数有三个 key data mode key为加密解密使用的密钥 data为加密解密的数据 mode为其工作模式 当模式为加密模式时 明文按照64位进行分组 形成明文组 key用于对数据加密 当
  • githubActions部署文件到服务器

    示例 githubAction配置示例 ssh秘钥方式 首先在服务器生成秘钥 参考https github com easingthemes ssh deploy 安装 rsync apt get install rsync 参考 参考 n
  • Go 流程控制 for、for range 循环

    在Go语言中 for循环是一种常用的流程控制语句 可以重复执行一段代码块 直到满足退出条件 同时 Go语言还提供了for range循环 用于遍历数组 切片 映射和字符串等数据结构 在本篇博客中 我们将介绍Go语言中的for循环和for r
  • USART HMI智能串口屏介绍

    概要 USART HMI智能串口屏 该显示屏的介绍 GUI界面的设计 通讯方式和修改控件参数的相关指令等 一开始我们项目组在显示上用的是12864液晶显示屏 带字库 但是看起来效果不是很好 感觉很LOW 而且不知道什么原因 12864常常会
  • Redis主从复制总结整理

    Redis的主从复制策略是通过其持久化的rdb文件来实现的 其过程是先dump出rdb文件 将rdb文件全量传输给slave 然后再将dump后的操作实时同步到slave中 让从服务器 slave server 成为主服务器 master
  • 实现文件里字符替换功能

    思路 首先要打开你要打开的文件例如我这边桌面的demo txt 利用相关函数计算出这个文件大小 然后开始遍历里面的内容 一个字符一个字符的遍历 如果找到了要被替换的字符就当场重新把新的内容赋值进去 最后重新覆盖整个文章 可能表达有误 可直接
  • mysql 5.6 安装流程

    一 首先解压安装包到指定路径 解压路径不可为中文 二 配置环境变量 我是windows11 1 1 2 3 4 5 6 6 全部点击确定 三 更改my ini 这两条路径更改为与环境变量相同路径 四 运行cmd 1 2 输入mysqld i
  • 2021-08-06软考网工的一个简单的综合实验

    拓扑 PC1和PC2都设置成dhcp获取ip PC1属于10网段 标记为教学区 PC2属于20网段 标记为宿舍区 LSW1作为接入交换机 LSW2作为核心交换机 AR1作为外网入口 AR2表示电信运营商的路由器 AR3表示联通运营商的路由器
  • oracle tcp空包请求,再谈 TCP 的 CLOSE_WAIT

    背景 某日集群告警 hbase regionserver 因 fd 不足导致进程主动退出 简单排查后发现regionserver 到 datanode 的TCP 连接存在大量 CLOSE WAIT 单机总数有10万之多 众所周知 CLOSE
  • HTML表格

    目录 实例 表格 表格和边框属性 表格的表头 表格中的空单元格 更多实例 表格标签 一个完整的实例 本例涉及到的资源 eg background jpg eg cute gif 可以使用 HTML 创建表格 实例 表格 这个例子演示如何在
  • 一台电脑上安装两个Tomcat服务器

    在排查问题来源的时候 由于不想卸载之前下载的Tomcat 需要再安装一个Tomcat服务器 下载压缩版的Tomcat之后 第一个Tomcat配置不变 需要修改第二个Tomcat的配置 1 CATALINA HOME 8081 新的地址 2
  • flex:1可以撑满剩余空间

    flex 1 的妙用 首先 flex 是 flex grow flex shrink flex basis的缩写 当 flex 取值为一个非负数字 则该数字为 flex grow 值 flex shrink 取 1 flex basis 取
  • MySql中left join、right join、inner join实例分析,union与union all的区别,Mybatis中CDATA []的用法

    inner join select from user a inner join grade b on a gid b id 只返回两个表中联结字段相等的行 left join select from user a left join gr
  • bokeh python_Python Bokeh数据可视化教程

    bokeh python Bokeh is an interactive Python data visualization library which targets modern web browsers for presentatio
  • cad隐藏图层命令快捷键_教你学会天正CAD局部隐藏对象技巧

    天正局部隐藏命令 JBYC 即局部隐藏的拼音首字母 其命令全称为TMKHIDE 适用于所有天正软件 建筑 电气 给排水 暖通 天正建筑的工具界面中是有此菜单的 且默认快捷键4为局部隐藏 6为恢复可见 其他软件并未显示 需要通过命令输入使用
  • 基于conda的相关命令

    conda 查看python版本环境 打开Anaconda Prompt的命令输入框 查看自己的python版本 conda env list 激活相应的python版本 环境 conda avtivate python 3 9 若输入以下
  • 我在工作中是如何使用【Linux】的

    目录 前言 一 常用命令 二 文件和目录处理 三 用户与组管理命令 四 进程管理命令 五 网络管理命令 六 帮助命令 七 磁盘管理 前言 大家好 这是我首篇博客 内容是linux工作需用到的内容 在这里我给大家总结出来了 希望多支持支持 感
  • 【Hello mysql】 mysql的事务

    Mysql专栏 Mysql 本篇博客简介 介绍mysql的事务 mysql的事务 事务的概念 事务功能测试 事务的隔离级别 如何理解隔离性 粗浅理解 隔离级别 查看和设置隔离级别 四种隔离级别详解 读 未提交 读 提交 可重复读 串行化 一