【MySQL】事务

事务,我们一直没有提到过它,它并不影响我们书写正确的sql语句,但并不意味着事务就不重要


目录

一、事务的概念

二、为什么会出现事务

三、事务的版本支持

四、事务的提交方式

五、事务的常见操作方式

5.1 准备

5.2 正常演示

5.2.1 开始一个事务

5.2.2 设置保存点

5.2.3 回滚

5.2.3.1 回滚至保存点

5.2.3.2 没有保存点的回滚

5.2.4 结束一个事务

5.3 异常演示

5.3.1 手动开启事务下的崩溃机制

5.3.2 自动提交事务下的崩溃机制

5.4 关于演示所得出的结论

5.5 事务操作的注意事项

六、事务的隔离级别

6.1 对于隔离性的理解

6.2 隔离级别

6.3 查看隔离级别

6.4 设置隔离级别

6.5 读未提交隔离性演示

6.6 读提交隔离性演示

6.7 可重复读隔离性演示

6.8 串行化隔离性演示


一、事务的概念

事务就是一组sql语句组成,这些语句在逻辑上存在相关性,这一组sql语句要么全部成功,要么全部失败,是一个整体。

MySQL提供一种机制,保证我们达到这样的效果。事务还规定不同的客户端看到的数据是不相同的。 事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。

假设一种场景:你毕业了, 学校的教务系统后台MySQL 中,不再需要你的数据,要删除你的所有信息, 那么要删除你的基本信息(姓名,电话,籍贯等)的同时,也删除和你有关的其他信息,比如:你的各科成绩,你在校表现,甚至你在论坛发过的文章等。这样,就需要多条MySQL语句构成,那么所有这些操作合起来,就构成了一个事务,这个事务就是用来删除学生所有信息的。

正如我们上面所说,一个 MySQL数据库,不止一个事务在运行,同一时刻,甚至有大量的请求被包装成事务,在向 MySQL服务器发起事务处理请求。这样如果大家都访问同样的表数据,在不加保护的情况,就绝对会出现问题。因为事务由多条 SQL 构成,那么,也会存在执行到一半出错或者不想再执行的情况,那么已经执行的怎么办呢? 所以,一个完整的事务,绝对不是简单的sql语句的集合,还需要满足如下四个属性:

原子性(Atomicity,或称不可分割性):一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中 间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

隔离性(Isolation,又称独立性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务 并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交( Read uncommitted )、读提交( read committed )、可重复读( repeatable read )和串行化 ( Serializable )。

持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完 全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。MySQL对一致性并没有做技术支持,但是只要事务满足了原子性、隔离性和持久性就一定可达到一致性的要求。

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

二、为什么会出现事务

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

下面正式开始讲解时我们把 MySQL中的一行信息,称为一行记录

三、事务的版本支持

在MySQL中只有Innodb存储引擎才支持事务, 其他的都不支持。

四、事务的提交方式

事务的提交方式常见的有两种: 自动提交和手动提交

我们可以使用下面语句来查看事务提交方式:

show variables like 'autocommit';

我们可以看到默认情况下是自动提交的

下面我们可以使用set autocommit来改变MySQL的自动提交模式:

将其设置为0,就关闭了自动提交

将其设置为1,就打开了自动提交

五、事务的常见操作方式

5.1 准备

为了演示事务的各种操作,我们先来做一些准备:

我们先将mysql的默认隔离级别设置成读未提交(后面会仔细讲解):

set global transaction isolation level READ UNCOMMITTED;

设置完后重启一下mysql客户端,再来查看一下默认隔离级别:

select @@tx_isolation;

可以看到这时默认事务隔离级别已经变成了读未提交

下面我们再来建一个表:

create table if not exists account(id int primary key,name varchar(50) not null default '',blance decimal(10,2) not null default 0.0
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

最后再登录一个mysql客户端,两个客户端对数据库同时访问,模拟并发操作:

5.2 正常演示

下面我们正式开始演示:

5.2.1 开始一个事务

我们想要开始一个事务可以使用语句:

start transaction;

或者

begin;

开始一个事务之后,在事务提交之前下面的所有sql语句都会被打包成一个事务

现在我们让两个客户端都开始事务:

5.2.2 设置保存点

在事务进行的时候我们可以在其过程中插入保存点:

savepoint 保存点名称;

我们先设置一个保存点,再向表中插入一些数据:

我们插入在一个客户端插入数据后可以看到,在另一个客户端可以看到插入的数据

下面我们继续一边设置保存点,一边插入数据:

插入完数据后,我们在另一个客户端可以看到插入的全部数据

5.2.3 回滚

我们可以使用rollback关键字来回滚

5.2.3.1 回滚至保存点

现在我们回滚至保存点s3:

我们可以看到王五这行记录不在了

下面我们回滚到s1保存点试试看:

我们可以发现,在s1保存点之后向表中插入的所有数据都不见了,回到了初始状态

5.2.3.2 没有保存点的回滚

回滚一定需要保存点嘛,如果我们在事务进行的时候不设置保存点会怎么样?

下面我们来进行演示,在事务进行时不设置保存点直接插入数据:

然后我们直接回滚:

可以看到,如果我们不设置保存点直接进行回滚,数据库将会撤销事务中所有语句的操作

5.2.4 结束一个事务

我们可以使用commit关键字来结束一个事务:

这时,开始语句和结束语句之间的所有sql语句都会被打包成一个事务

5.3 异常演示

上面的演示是基于事务正常commit结束的,下面我们演示一下,在事务进行的过程中客户端崩溃,MySQL的机制:

5.3.1 手动开启事务下的崩溃机制

现在表中是没有数据的:

我们使用begin语句手动开始事务,用另一个客户端向表中插入数据;

在事务进行的过程中,数据都被保留下来了,下面我们没有commit来结束这个事务,而是让插入数据的客户端直接崩溃:

我们可以看到如果事务在没有正常commit的情况下,客户端崩溃,MySQL自动会回滚

那如果正常commit了呢?

我们可以看到如果事务已经commit了,客户端崩溃,MySQL数据不会在受影响,已经持久化

5.3.2 自动提交事务下的崩溃机制

我们之前写的sql语句都是在begin手动开启一个事务下进行的,那我们不使用开始事务的语句,单条执行sql语句会怎么样呢?

我们现在开启了自动提交事务,下面我们直接使用sql语句插入数据试试看:

我们可以看到可以正常插入数据,接着我们让客户端崩溃试试看:

可以看到在开启事务自动提交的情况下,单条sql语句执行后,数据已经持久化,不会受到客户端崩溃的影响

下面我们关闭自动提交事务来试试:

插入数据是正常的,接着我们让客户端崩溃:

我们看到客户端崩溃后,因为没有设置自动提交事务,所有进行的单句sql会被滚回

那在我们关闭自动提交事务时,在插入数据后,使用commit会怎么样呢?

下面让客户端崩溃:

我们可以看到在没有设置自动提交事务的情况下,我们使用commit手动提交后,数据会被持久化,客户端崩溃并不会再进行回滚

5.4 关于演示所得出的结论

只要输入begin或者start transaction,事务便必须要通过commit提交,才会持久化,与是否设置set autocommit无关。

事务可以手动回滚),同时,当操作异常,MySQL会自动回滚

对于InnoDB每一条SQL语言都默认封装成事务,自动提交。(select有特殊情况,因为 MySQL 有 MVCC)

从上面的例子,我们能看到事务本身的原子性(回滚),持久性(commit)

5.5 事务操作的注意事项

如果没有设置保存点,也可以回滚,但只能回滚到事务的开始。

直接使用rollback(前提是事务还没有提交),如果一个事务被提交了(commit),则不可以滚回(rollback)

可以选择回滚到哪个保存点

InnoDB 支持事务, MyISAM 不支持事务

六、事务的隔离级别

6.1 对于隔离性的理解

MySQL服务可能会同时被多个客户端进程(线程)访问,访问的方式以事务方式进行。一个事务可能由多条SQL构成,也就意味着,任何一个事务,都有执行前,执行中,执行后的阶段。而所谓的原子性,其实就是让用户层,要么看到执行前,要么看到执行后。执行中出现问题, 可以随时回滚。所以单个事务,对用户表现出来的特性,就是原子性。

但所有事务都要有个执行过程,那么在多个事务各自执行多个SQL的时候,还是有可能会出现互相影响的情况。比如:多个事务同时访问同一张表,甚至同一行数据。

就如同你妈妈给你说:你要么别学,要学就学到最好。至于你怎么学,中间有什么困难,你妈妈不 关心。那么你的学习,对你妈妈来讲,就是原子的。那么你学习过程中,很容易受别人干扰,此 时,就需要将你的学习和其他事情隔离开,保证你的学习环境是健康的。

数据库中,为了保证事务执行过程中尽量不受干扰,就有了一个重要特征:隔离性

数据库中,允许事务受不同程度的干扰,就有了一种重要特征:隔离级别

6.2 隔离级别

读未提交【Read Uncommitted】: 在该隔离级别,所有的事务都可以看到其他事务没有提交的执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多并发问题,如脏读,幻读,不可重复读等,我们上面为了做实验方便,用的就是这个隔离性。

读提交【Read Committed】 :该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL默认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次select, 可能得到不同的结果。

可重复读【Repeatable Read】: 这是MySQL默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是在一般数据库下会有幻读问题,在MySQL下已经解决了幻读问题。

串行化【Serializable】: 这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突, 从而解决了幻读的问题。它在每个读的数据行上面加上共享锁,但是可能会导致超时和锁竞争 (这种隔离级别太极端,并发效率太低,实际生产基本不使用)

6.3 查看隔离级别

查看全局隔级别

SELECT @@global.tx_isolation;

查看会话(当前)隔级别

SELECT @@session.tx_isolation;

或者

SELECT @@tx_isolation;

6.4 设置隔离级别

设置全局隔级别

SET GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别名称;

设置会话(当前)隔级别

SET SESSION TRANSACTION ISOLATION LEVEL 隔离级别名称;

需要注意的是:设置全局隔离级别后,不会影响已开启的会话,但另起一个会话,会被影响

6.5 读未提交隔离性演示

在事务的常见操作方式中我们一直是用读未提交的隔离级别进行演示的,所以这里不再进行重复。

从演示的过程中我们可以看到:一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种现象叫做脏读

6.6 读提交隔离性演示

我们先修改一下全局隔离级别

下面两个并发的客户端一起手动启动事务:

现在左边客户端修改表中的数据:

再用右边的客户端来查看:

可以发现数据并没有被修改,接下来我们提交左边客户端的事务,再用右边的客户端查看数据:

左边客户端commit之后,右边客户端看到了被修改的数据了 

但此时右边客户端还在当前事务中,并未commit,那么就造成了,同一个事务内,同样的读取,在不同的时间段 ,读取到了不同的值,这种现象叫做不可重复读(non reapeatable read)

在逻辑上这似乎没什么问题,但是在实际开发中每次读取的数据不同会影响最终的决策结果,会造成不合理的情况

6.7 可重复读隔离性演示

废话不多说,我们直接来演示:

先来删除个数据:

左边客户端删除后,在右边客户端查询一下:

没有任何反应,下面我们提交左边客户端的事务:

用右边客户端再查询一下:

还是没有任何的变化,接下来我们提交右边客户端的事务,再来查询一下:

此时我们才能看到id=1的记录被删除了

在可重复读隔离性下,多次查看,发现左边客户端在对应事务中delete的数据,在右边的事务周期中,也没有什么影响,也符合可重复的特点。

但是,一般的数据库在可重复读隔离性下,无法屏蔽其他事务insert的数据(因为隔离性实现是对数据加锁完成的,而insert待插入的数据因为并不存在,那么一般加锁无法屏蔽这类问题),会造成虽然大部分内容是可重复读的,但是insert的数据在可重复读情况被读取出来,导致多次查找时,会多查找出来新的记录,就如同产生了幻觉,这种现象叫做幻读 (phantom read)。

但是MySQL在RR级别的时候,是解决了幻读问题的(解决的方式是用Next-Key锁 (GAP+行锁))。

6.8 串行化隔离性演示

我们先在左边的客户端开始begin,再在右侧的客户端开始begin:

我们可以看到左边客户端对数据进行修改非常的快,但是我们使用右边的客户端对表进行select查找却卡住了

接着我们提交左边客户端的事务,发现右边客户端的查询语句出结果了:

在串行化隔离下,系统不确定左边客户端是否还有更新或者其他操作,会先阻塞右边客户端的读取,直到左边客户端事务提交

这样子导致了右边客户端的读取语句耗时15.66s才结束,在高并发下效率是很低的

隔离级别越严格,安全性越高,但数据库的并发性能也就越低,需要在两者之间找一个平衡点。


更多MySQL技能请看:http://t.csdn.cn/W9dQl

博主努力更新中~

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

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

相关文章

linux-shell编程

shell编程 1. 变量、条件判断、流程控制、函数 $n (功能描述:n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,十以上的参数,十以上的参数需要用大括号包含,如${10}) $# &…

html(七)meta标签

一 meta标签 1、背景:发现自带某些请求头2、本文没有实际的生产应用场景,仅仅作为技术积累 ① meta标签含义 1、metadata: 元数据,是用于描述数据的数据,它不会显示在页面上,但是机器却可以识别2、应用场景: [1]、SEO搜索引擎优化[2]、定义页面使用…

IP库新增经过实践的Verilog 库

网上严重缺乏实用的 Verilog 设计。Project F 库是尝试让 FPGA 初学者变得更好部分。 设计包括 Clock- 时钟生成 (PLL) 和域交叉Display - 显示时序、帧缓冲区、DVI/HDMI 输出Essential- 适用于多种设计的便捷模块Graphics- 绘制线条和形状Maths- 除法、LFSR、平方根、正弦....…

【系统架构】系统架构设计之数据同步策略

文章目录 一、介绍1.1、分布式系统中的数据同步定义1.2、为何数据同步如此关键1.3、数据同步策略简介 二、为什么需要数据同步2.1、提高系统可用性2.2、备份与灾难恢复2.3、提高性能2.4、考虑地理位置(如使用CDN) 三、同步备份3.1、定义和概述3.2、工作原…

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数

线程池改造 上一篇文章中我们用了Excutors创建了线程,这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…

代码随想录算法训练营第四十一天 | 343. 整数拆分,96.不同的二叉搜索树

代码随想录算法训练营第四十一天 | 343. 整数拆分,96.不同的二叉搜索树 343. 整数拆分动态规划贪心 96.不同的二叉搜索树 343. 整数拆分 题目链接 视频讲解 给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k > 2 )&#xff…

Java源码分析(一)Integer

当你掌握Java语言到了一定的阶段,或者说已经对Java的常用类和API都使用的行云流水。你会不会有一些思考?比如,这个类是如何设计的?这个方法是怎么实现的?接下来的一系列文章,我们一起学习下Java的一些常见类…

香港服务器备案会通过吗?

​  对于企业或个人来说,合规备案是网络运营的基本要求,也是保护自身权益的重要举措。以下内容围绕备案展开话题,希望为您解开疑惑。 香港服务器备案会通过吗? 目前,香港服务器无法备案,这是由于国内管理规定的限制…

人工智能引领图文扫描新趋势

1. 背景和影响 近日,中国大学生服务外包创新创业大赛决赛在江南大学圆满落幕。为满足现代服务产业企业的现实需求,本次竞赛内容设计充分聚焦企业发展中所面临的技术、管理等现实问题,与产业的结合度更紧密,智能文字识别技术是大赛…

Unity VR:XR Interaction Toolkit 输入系统(Input System):获取手柄的输入

文章目录 📕教程说明📕Input System 和 XR Input Subsystem(推荐 Input System)📕Input Action Asset⭐Actions Maps⭐Actions⭐Action Properties🔍Action Type (Value, Button, Pass through) ⭐Binding …

前端框架Vue

Vue 学习路线 学习HTML、CSS和JavaScript基础知识:Vue是基于JavaScript的框架,所以首先需要掌握HTML、CSS和JavaScript的基础知识,包括DOM操作、事件处理、变量和函数等。 学习Vue的基本概念:了解Vue的核心概念,如Vu…

Win10+anaconda+CUDA+pytorch+vscode配置

Win10anacondaCUDApytorchvscode配置 1.安装anaconda2.安装CUDA确认CUDA版本确认CUDA和pytorch版本安装CUDA 3.安装cudnn4.安装Pytorch5.vscode配置安装VScodevscode配置pytorch环境 1.安装anaconda 官网https://www.anaconda.com 下载安装,路径全英文然后记得有一…

【RabbitMQ】消息队列-RabbitMQ篇章

文章目录 1、RabbitMQ是什么1.1、RabbitMQ---使用场景一般场景解耦削峰异步 2、Dokcer安装RabbitMQ2.1安装Dokcer2.2安装rabbitmq 3、RabbitMQ入门案例 - Simple 简单模式4、RabbitMQ的核心组成部分4.1 RabbitMQ整体架构4.2RabbitMQ的运行流程 5、RabbitMQ的模式5.1 发布订阅模…

大数据-玩转数据-Flink App市场推广统计

一、说明 电商网站中已经有越来越多的用户来自移动端,相比起传统浏览器的登录方式,手机APP成为了更多用户访问电商网站的首选。对于电商企业来说,一般会通过各种不同的渠道对自己的APP进行市场推广,而这些渠道的统计数据&#xf…

iOS自定义下拉刷新控件

自定义下拉刷新控件 概述 用了很多的别人的下拉刷新控件,想写一个玩玩,自定义一个在使用的时候也会比较有意思。使应用更加的灵动一些,毕竟谁不喜欢各种动画恰到好处的应用呢。 使用方式如下: tableview.refreshControl XRef…

小程序多图片组合

目录 子组件 index.js 子组件 index.wxml 子组件 index.wxss 父组件引用: 子组件:preview-image 子组件 index.js Component({properties: {previewData: {type: Array,default: [],observer: function (newVal, oldVal) {console.log(newVal, ol…

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现GWO-SVM灰狼优化算法优化支持向量机多输入单输出回归预测(多指标,多图)效果一览基…

图论基础和表示(Java 实例代码)

目录 图论基础和表示 一、概念及其介绍 二、适用说明 三、图的表达形式 Java 实例代码 src/runoob/graph/DenseGraph.java 文件代码: src/runoob/graph/SparseGraph.java 文件代码: 图论基础和表示 一、概念及其介绍 图论(Graph Theory)是离散数…

MySQL基础篇(二)

DML 定义:Data Manipulation Language、数据操作语言(增删改) 添加数据(INSERT)修改数据(UPDATE)删除数据(DELETE) 添加数据(INSERT) 给指定的…

Nginx:网站服务

nginx:一个高性能、轻量级的web服务软件 1、稳定性高(没有apache稳) 2、系统资源消耗低(处理http请求的并发能力很高,单台物理服务器可以处理3万到5万个并发请求) 稳定:一般在企业中&#xff…