mysql查看版本号_十分钟了解MySQL事务机制

读书百遍其义自现。

74371771c85b59c6c3730afae4c4ea8f.png

MySQL数据库在我们平时工作学习中的使用频率是相当之高,彻底掌握MySQL的事务机制对我们平时工作会有非常大的帮助,仔细回忆一下,你是否对MySQL事务相关的知识是否完全掌握?是否感觉有的地方有些模糊?通过这篇文章让你彻底理顺逻辑,下面就开始吧!

01事务的特性

事务的特点

提到数据库的事务,我们肯定脱口而出的就是ACID,但是有的时候并不清楚ACID到底是什么,掌握事务的特性对于我们接下来学习是相当重要的。

首先举个例子,老王去银行转账的例子将农业银行的100元转到老刘农业银行卡,主要有以下三步

1.首先判断老王的农业银行的账户金额是否大于100元

2.老王的农业银行的账户余额减去100元

3.老刘的农业银行的账户余额加100元

试想一下如果其中某一步失败就会导致非常严重的问题,我们需要把操作放到一个事务中去执行,如果其中有一步执行失败,那么所有操作都将回滚,通过这种方式来保证数据一致性。

 start transaction;select balance from account where uid = 60610;update account set balance = balance - 100 where uid = 60610;update account set balance = balance + 100 where uid = 60611;commit;

原子性(atomicity)

原子在化学中表示不可再进行分割的基本微粒,在事务表示的是这是一个不能再被分割的最小工作单元,整个事务的所有操作,要么全部成功,要么全部失败回滚,而不可能仅仅执行某一部分。

一致性(consistency)

数据库总是从一个一致性的状态转化到另一个一致性的状态,老王转账即使第二步和第三步之间系统崩溃了,也不会出现问题,因为数据并没有提交,没有提交事务,所做的修改也并不会保存到数据库中。

隔离性(isolation)

通常来说,一个事务所做的修改在最终提交前,对其他的事务是不可见的,这里为什么说“通常是不可见的”,因为这和具体的事务隔离级别有关,后面我们会进行分析。

持久性(durability)

一旦事务提交,则其他的修改就会永远保存到数据库中。即使系统崩溃,修改的数据也不会丢失。

02事务隔离级别

事务隔离级别

所谓事务隔离级别,就是用来定义一个事务所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统开销也更低 。

在MySQL中一共有四种事务隔离级别:读未提交、读提交、可重复读、可串行化,下面我们将分别简单介绍四种隔离级别。

读未提交 read uncommitted

在此事务隔离级别下,修改数据库中的数据,即使没有提交,对其他事务也是可见的。事务可以读到未被提交的数据,这种情况也被称为脏读,这种隔离级别下会出现很多问题,但性能也不会比read committed好太多。

读提交 read committed

大多的数据库的默认事务隔离都是读提交,但是MySQL的默认事务隔离基本是可重复读,在这种隔离级别下,只有当事务提交后,事务中的修改才会对其他事务可见,但是会出现在同一个事务中多次查询数据结果可能不同,因为中间可能有修改数据的事务提交了,这种现象叫不可重复读

可重复读 repeatable read

该级别不仅解决了脏读,还可以在一个事务中,同一个事务多次读取同样的记录结果是一样,但是理论上,还是无法解决幻读现象,所谓幻读,就是在一个事务执行中,其他事务插入了新的行并且提交,就会产生幻行。但实际上MySQL通过MVCC(多版本并发控制)解决了幻读的问题。

可串行化 serializable

该级别是最高的隔离级别,避免了前面说的幻读的问题,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。实际中很少使用这个隔离级别,因为使用这个隔离级别,几乎没有并发可言。

各个事务级别对应的能力

4c07f4b92c613c53690db5c072474b59.png

03验证事务隔离级别

MySQL基础设置

首先登录MySQL。

d26955150351473ca1483fc225ae692b.png

查看当前数据库

9969f3573c755faec9f06f5d6c38082b.png

创建测试数据库

48b408a903d8cb4a4f69915e56aa7fa0.png

可以看到刚刚新建的数据库

a11f69dab94e6cc9ececf6e9fb703aa8.png

使用刚刚创建的数据库

2c93415a7d8b2e40ddf5b3e6ae443993.png

创建测试表

9366749014b85e2dbfac41d48e57f3bf.png

 create table tb_user (    id bigint not null auto_increment comment "用户id",    name varchar(50) not null comment "用户姓名",    age int not null comment "用户年龄",    balance int not null comment "用户余额",PRIMARY KEY (`id`))ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8 COMMENT='用户表';

初始化数据

dcd74b82e3e216d8147ff4105cad5b87.png

SQL数据

 insert into tb_user(name, age, balance) values('老王', 24, 100);insert into tb_user(name, age, balance) values('老刘', 25, 500);

测试之前做的一些准备

MySQL中默认的是事务自动提交的,在测试我们需要控制事务提交的时机,所以我们将MySQL改为非自动提交事务,这种方式仅仅是当前session关闭自动提交。

bb92a8c81d8868b16535fb029374be2a.png

设置全局关闭自动提交

290ec9e228dcd15fc72fc8b0e49741de.png

查看自动提交事务状态,可以看到当前session和全局的自动提交都已经关闭。

3ffda06989c36af3941b52b1a8d228d6.png

验证读未提交 read uncommitted

这里我们约定,每次测试完成后都将余额还原成初始值,即老王余额100元,老刘余额500元。

因为MySQL的默认事务隔离级别是可重复读,我们先将当前session的事务隔离级别设置为读未提交。

2442e6431d99aac1ac965ada468d9ad9.png

修改之后的事务隔离级别

74769ba1d0c61b6588c1830ecf93b572.png

下面启动两个事务A、B并设置它们的事务隔离级别为读未提交。

6662774a4ae3837b8eaf03f8322b3371.png

开启事务A和事务B

fbd12a96ec3c4dbb0996d0525d7c6340.png

afe006db6a29c86c6d212d2348548d20.png

事务A查询老王的余额(下图应是查询结果)

5fe4a42765ac2b44409b3eb47a1c2f8b.png

老王充值50元

5fe4a42765ac2b44409b3eb47a1c2f8b.png

事务B读到了未提交的数据,出现了脏读。

b89a2738d9accc20c0ed3fe9c0efd561.png

事务A回滚

8d5bef9286ca771b028e7db9d7bea380.png

老王账户减少150元,并提交事务B

479ce1f730a56672554f07a17caa7097.png

此时查看老王的账户余额可以发现为-50,可以看出由脏读引发的问题。

70299a018d1b0bbfa3979a4c68a26031.png

验证读已提交 read committed

首先我们需要把数据进行初始化,即老王余额100元,老刘余额500元。将两个session的事务隔离级别设置为读已提交。

add544bd61cdcf91e9d808c08c8f9935.png

让事务A、B依次执行测试读未提交时的逻辑,同样的条件下,在读已提交的情况下,事务B并没有读到脏数据。

12fcc6b37965e76cf9a6f7656c36b718.png

接下来,我们做下一组测试,事务A和事务B按照下面的顺序进行执行。

52afcef0e415854bfcd32a911186dccc.png

事务B查询老刘账户余额为500元。

8f47a39f13cbc372b67477060794b4ce.png

事务A向老刘账户充值500元并提交事务。

dc7d2d72cd0dcfcbf8280a8d0dbfef71.png

事务B再次查询老刘的余额,为1000元,在同一个事务中,重复进行查询返回的结果不同,这就是不可重复读。

66123e357228c786cb678e1cc9dc4c0f.png

可重复读 repeatable read

首先我们需要把数据进行初始化,即老王余额100元,老刘余额500元。将两个session的事务隔离级别设置为可重复读。

e9fab22be609916e80483e6b2b364417.png

下面我们启动事务A、B,重新按顺序执行读已提交的测试逻辑,通过测试我们发现,在可重复读级别下,在同一个事务中多次查询结果是一致的,解决了不可重复读。

099fb08cc1b197b8c19c450c3e6cf3ab.png


接下来,我们来看另一组测试,把数据进行初始化,即老王余额100元,老刘余额500元。

5893ba6583b7326704bfa16cfda88307.png

查询当前用户表中有几个用户,可以看到查询到了两个用户。

56b55a8ec27bab7c30cca68a8bbc34ca.png

在事务B中插入用户老赵,并提交事务,此时数据中应该有三条记录。

7f718780357f51e35a53d8cee4e421d3.png

在事务A中查询数据库记录条数,我们发现记录数还是2,说明MySQL在repeatable read级别成功避免了幻读,那么MySQL是如何在RR级别避免幻读的呢?下文会进行分析。

91c526a7d70f77c62fa94c66655c5416.png

验证可串行化 serializable

这里没有对可串行化 serializable隔离级别进行验证,因为在此隔离级别会给所有的读取行加锁,所有事务只能串行执行。

04MVCC如何解决幻读问题

MVCC(Multiversion Concurrency Control)即多版本并发控制,大多数的数据库都实现了MVCC,但是实现机制各不相同,并且没有统一的标准。

以InnoDB引擎为例,对MVCC的工作流程进行讲解。

在使用InnoDB引擎的表中是通过在每条记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建的时间,另一个保存行的删除时间。

5a5ffca6fdf5fc286816da41ca8ef09e.png

这里其实保存的并不是创建时间,而是系统的版本号(system version number)。每开始一个新事务,系统版本号都会自动递增,事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录版本号进行比较。

b1133188a085da899d7f25fbee262e13.png

下面通过在repeatable read隔离级别下,对于增删改查MVCC是如何操作的。

SELECT查询

InnoDB会根据两个条件去检查每行记录。

1、InnoDB只查版本早于当前事务的数据行(也就是,行的创建版本号小于或者等于事务的系统版本号),这样做是为了保证,事务读取的行,要么是事务开始前已经存在了,要么是事务自身插入或者修改过的。

2、关于行的删除版本,我们读取的行,要么没有定义,要么大于当前事务的系统版本号(这说明是事务开启之后修改的),这样就可以确保我们读取到的数据,都是在事务开启之前未删除。

这也就解释了为什么在可重复级别可以避免幻读,等同于给数据库的表和数据做了一个快照,相当于在一个视图上进行操作,无论其他事务怎么修改数据,在当前事务提交之前,多次查询的结果都是相同的,除此之外我们可以发现,在数据库中同一条记录可能存在多个版本。

INSERT插入

InnoDB为新插入的每一行保存当前事务的系统版本号,作为行的创建版本号。

DELETE删除

InnoDB为删除的每一行保存当前事务的系统版本号,作为行删除标记。

UPDATE更新

InnoDB为插入一行新记录,保存当前事务系统版本号作为行的创建版本号,同时保存当前事务的系统版本号作为行删除标记。

关于MVCC

通过上述介绍的机制,通过两个额外的版本号字段,使得大多数的读操作不需要加锁,这样设计使得读数据操作很简单,性能很好,但是需要额外的存储空间,并且需要更多的检查和维护工作。

此外,MVCC只在REPEATABLE READ和READ COMMITTED两个隔离级别下工作。其他两个隔离级别和MVCC都不兼容,因为读未提交总是读取最新的数据行,而可串行化则会对所有行都加锁。

05总结

本文主要介绍了,MySQL的事务的特性ACID,除此还介绍了事务的各个隔离级别的特征,不同的隔离级别会出现什么样的问题,理论上,事务的隔离级别越高消耗的资源越多,在平时的业务开发中,需要根据业务特点去选择不同的事务隔离级别,最后我们介绍了MVCC,并说明它如何解决幻读问题的,以及MVCC在可重复读下,增删改查的操作,希望读者能够掌握本文的内容,相信对理解MySQL的事务会有一定的帮助。

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

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

相关文章

mysql 字符串类型 分区_MySQL分区类型

博文大纲:1、RANGE分区2、LIST分区3、HASH分区4、key分区5、MySQL分表和分区的区别6、附加:如何实现将分区放在不同的目录下进行存储MySQL分区类型如下:RANFGE分区LIST分区HASH分区key分区上面的四种分区的条件必须是整形,如果不是…

mysql免安装如何改密码_mysql免安装版配置与修改密码的教程

第一步:配置环境变量(我的解压路径:G:\mysql\mysql-5.7.21-winx64 )MYSQL_HOME你解压的路径PATH ;%MYSQL_HOME %\bin;PATH变量是在原来的基础上多添加的,不要把其它的设置给删掉了第二步在解压的目录下添加my.ini 文件(如果已经有了这个文件&#xff0c…

拉普拉斯时域卷积定理_如何证明频域卷积定理

展开全部设抄IF表示傅立叶逆变换,则因此有袭故频域卷积定2113理5261得证。4102扩展资料频域卷积定理频域卷积定理表明两信号1653在时域的乘积对应于这两个信号傅立叶变换的卷积除以2π。卷积定理揭示了时间域与频率域的对应关系。这一定理对Laplace变换、Z变换、Mel…

suse查看mysql内存使用情况_MySQL 慢查询日志(Slow Query Log)

4、格式化慢查询日志结构化慢查询日志就是把慢查询日志中的重要信息按照便于阅读以及按照特定的排序方式来提取SQL。这种方式有点类似于Oracle中有个tkprof来格式化oracle的trace文件。对于前面的慢查询日志我们使用MySQLdumpslow来提取如下:SUSE11b:~ # mysqldumps…

mysql 分析服务_MySQL分析服务器状态_MySQL

概述文章简单介绍了通过一些查询命令分析当前服务器的状态。目录概述获取服务器整体的性能状态SQL操作计数总结步骤获取服务器整体的性能状态首先对一个数据库服务器进行性能优化需要先知道服务器当前主要的性能问题出现在哪里,在这点sql server也是类似&#xff0c…

python 接口测试 如何写配置文件_python接口自动化测试 - configparser配置文件解析器详细使用...

configparser简介ConfigParser模块已在Python 3中重命名为configparser该模块定义了ConfigParser类。 ConfigParser类实现一种基本的配置文件解析器语言,该语言提供的结构类似于 .ini 文件中的结构ini文件相关知识键值对可用 或者 : 进行分隔section 的名字是区分大…

java jdom 设置第1行_Java通过jdom操作生成XML文件的实例代码下载

工作需要,要生成xml文件,所以做了个小demo分享一下。看代码吧~ main()里面没什么好说的 该写的都写了public static void main(String[] args) {//调用 DocumentBuilderFactory.newInstance() 方法得到创建 DOM 解析器的工厂DocumentBuilderFactory fact…

java 对象工厂_Java设计模式之--工厂方式

在分析工厂模式之前,我们先看看普通模式下的Java三层结构。Controller(表现层)-Service(业务层)-Dao(持久层、数据库连接层),基于此三层结构完成JavaWeb相关业务。假设我们要完成的业务是添加员工信息,先创建Dao包,创建EmpDao接口和EmpDaoFac…

mysql 5.7 io 性能 aio_深入理解MySQL的InnoDB引擎

在MySQL中的引擎一文中说了,我们在几乎所有的情况下其实用的都是InnoDB引擎,这里我们就重点再看一下这个引擎,包括他的存储结构,线程模型和数据文件。我们可以通过show engine innodb status \G;(\G只是表示输出结果纵向表格输出)…

mysql构建数据立方体_OLAP数据建模工具Workbench的初步使用(数据立方体的建立)

OLAP数据建模工具Workbench的初步使用(数据立方体的建立)概要:1.workbench工具简介2.workbench简单操作(附demo)3.workbench初步使用总结1.workbench工具简介OLAP,(Online Analytical Processing,联机分析处理)。从事相关工作的小伙伴,具体的…

java循环1000000000_求十亿内所有质数的和,怎么做最快?

注:对知乎的公式编辑功能实在无力吐槽,用typora写的文章直接粘过来公式无法显示,只好又手工加上了全部公式,不过可能还是会有遗漏。大家可以点击这个链接 查看我的博客原文。以下是正文:第一次关注到这个问题是在做pro…

java飞行记录器是什么_运行java飞行记录器JFR(java flight recorder)

JFR上面讲到的工具都是作为快速的查看诊断工具的。如果要深入分析问题,可以选择使用内置的Java飞行记录器:Java Mission Control。转储JFR需要三步:1. 创建一个包含了你自己配置的JFR模板文件。运行jmc, 然后Window->Flight Recording Template Manag…

java申请安卓权限_java4android (包和访问权限)

什么是Java当中的软件包?为什么要使用软件包?如何给一个类打包?//将类放置到一个包中,需要使用package“包名”//打包 编译的方法 javac -d . Test.java//出现错误:编码GBK的不可映射字符 javac -encoding UTF-8 -d . …

php 条形码生成器,PHP条形码图像生成器

这是一个用于生成barocdes的简单PHP脚本://For displaying barcodes//Arguments are:// code Number you want outputted as a barcode//You can use this script in two ways:// From a webpage/PHP script // Directly in your web browser http://www.example.co…

java欧冠抽签,欧冠抽签吐槽:最大的“礼包”被C罗拿走!梅西出局概率超50%?...

欧冠16强抽签揭晓,结果:多特VS巴黎,皇马VS曼城,亚特兰大VS瓦伦西亚,马竞VS利物浦,切尔西VS拜仁,里昂VS尤文图斯,热刺VS莱比锡,那不勒斯VS巴萨。怎么评价这样的抽签呢&…

matlab 流固耦合,详讲流固耦合

引言近来,航空航天工业在世界上发展迅速,而作为“飞机心脏”的航空发动机是限制其发展的主要因素。目前,航空发动机日益向高负荷、高效率和高可靠性的趋势发展,高负荷导致的高逆压力梯度容易引起流动分离,同时随着科技…

php提示是否运行,php运行错误提示

第一种方法在php.ini文件里改变display_errors和error_reporting的值,没有的直接加上。; 第一处修改; display_errors Offdisplay_errors On; 第二处修改; error_reporting E_ALL & ~E_DEPRECATED & ~E_STRICTerror_reporting E_ALL | E_STRICTdisplay_…

usb转ttl模块与matlab,图文详解USB转TTL设备与电路板的连接

描述USB转TTL的硬件设备:USB转TTL主机一台;芯片选用PL-2303HXUSB转TTL刷机线,采用进口PL2303HX芯片。连接上电脑并安装驱动后,电脑即扩展出一个COM3或COM4....等的串口,配合相应软件就能对路由器、机顶盒或接收机等各种TTL接口的设备系统进行…

php乱码调试,NotePad++ 调试PHP代码中文显示乱码

最近在NotePad上调试PHP代码,按照示例代码进行调试,结果在显示中文的时候显示一堆乱码,于是上网百度,有2种方法可以解决:按调试方式有2种方法:1、菜单插件-NppExec:“插件”-“NppExec”-"Console Out…

php怎么设置网站的字符编码,php如何设置字符编码

php如何设置字符编码?a. 如果欲使用gb2312编码,那么php要输出头:header(“Content-Type: text/html; charsetgb2312"),静态页面添加,所有文件的编码格式为ANSI,可用记事本打开,另存为选择编…