【MySQL进阶】MySQL事务详解

news2024/11/15 15:33:25
序号系列文章
5【MySQL基础】字符集与校对集详解
6【MySQL基础】MySQL单表操作详解
7【MySQL基础】运算符及相关函数详解
8【MySQL基础】MySQL多表操作详解

文章目录

  • 前言
    • 1,事务概念
    • 2,事务四大特性
      • 2.1,原子性
      • 2.2,一致性
      • 2.3,隔离性
      • 2.4,持久性
    • 3,事务基本操作
      • 3.1,开启事务
      • 3.2,回滚事务
      • 3.3,提交事务
      • 3.4,事务的保存点
      • 3.5,事务自动提交
      • 3.6,事务访问模式
      • 3.7,事务操作注意
    • 4,隔离级别操作
      • 4.1,查看隔离级别
      • 4.2,修改隔离级别
    • 5,事务并发问题
      • 5.1,脏读
      • 5.2,不可重复读
      • 5.3,幻读
    • 6,事务隔离级别
      • 6.1,READ UNCOMMITTED
      • 6.2,READ COMMITTED
      • 6.3,REPEATABLE READ
      • 6.4,SERIALIZABLE
  • 结语

前言

大家好,我是小杨!前面我为大家介绍完了MySQL中的基础知识,那么从今天开始我将为大家介绍MySQL中的进阶知识,那么今天我们就从MySQL中的事务这部分内容开始说起,希望大家能够收获多多!


1,事务概念

事务就是针对数据库的一组操作,它是由一条或多条SQL语句组成,且每个SQL语句之间是相互依赖的。

只要在程序执行过程中有一条SQL语句执行失败或发生错误,则其他的SQL语句都不会被执行。

简而言之,事务的执行要么成功,要么就返回至事务开始前的状态。

就比如,张三要给李四转账1000块钱,张三银行账户的钱减少1000,而李四银行账户的钱要增加1000。

转账流程可以大致分为三部分来完成:1,查询张三账户余额 2,张三账户余额-1000 3,李四账户余额+1000

只有这三个部分都完成才认为转账成功。

在数据库中,这个过程是使用三条SQL语句来完成的。

#1,张三账户余额查询
SELECT id,name,money FROM ccount WHERE name = '张三';

#2,张三账户减少1000元
UPDATE account SET money = money - 1000 WHERE name = '张三';

#3,李四账户增加1000元
UPDATE account SET money = money + 1000 WHERE name = '李四';

正常情况: 转账这个操作, 需要分为以下这么三步来完成 , 三步完成之后, 张三减少1000, 而李四增加1000, 转账成功 :

image-20230121205632764

异常情况: 转账这个操作, 也是分为以下这么三步来完成 , 在执行第三步是报错了, 这样就导致张三减少1000块钱, 而李四的金额没变, 这就会导致两个账户的金额不同步,造成错误。

image-20230121210104759

为了解决上述的问题,就需要通过数据的事务来完成,我们只需要在业务逻辑执行之前开启事务,执行完毕后提交事务。如果执行过程中报错,则回滚事务,把数据恢复到事务开始之前的状态。

image-20230121211804375


2,事务四大特性

2.1,原子性

原子性是指一个事务必须被视为一个不可分割的最小工作单元,只有事务中所有的数据库操作都执行成功,才算整个事务执行成功。

如果事务中有任何一个SQL语句执行失败,已经执行成功的SQL语句也必须撤销,数据库的状态退回到执行事务前的状态。

简而言之,原子性指的是:事务是不可分割的最小操作单元,事务中的操作执行要么全部成功,要么全部失败。


2.2,一致性

一致性是指在进行事务处理时,无论是执行成功还是失败,都要保证数据库系统处于一致的状态,保证数据库系统不会返回到一个未处理

的事务中。MySQL中的一致性主要是由日志机制来实现的,通过日志记录数据库的所有变化,为事务恢复提供了跟踪记录。

简而言之,一致性指的是:事务完成时,必须使所有的数据都保持一致的状态。


2.3,隔离性

隔离性是指当一个事务在执行时,不会受到其他事务的影响。保证了未完成事务的所有操作与数据库系统的隔离,直到事务完成为止,才能看到事务的执行结果。隔离性相关的技术有并发控制、可串行化、锁等。

当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

简而言之,隔离性指的是:数据库系统提供的隔离机制,保证了事务不受外部并发操作的影响,而在独立环境下运行。


2.4,持久性

持久性是指事务一旦提交,其对数据库的修改就是永久性的。但需要注意的是,事务的持久性不能做到百分百的持久,只能从事务本身的角度来保证永久性,而一些外部原因导致数据库发生故障,如硬盘损坏,那么所提交的数据可能都会丢失。

简而言之,持久性指的是:事务一旦提交或者回滚,它对数据库中的数据的改变就是永久的。


3,事务基本操作

3.1,开启事务

默认情况下,MySQL的提交方式是自动提交模式,也就是说用户执行的每一条SQL语句都会被当成一个单独的事务自动提交。如果不想执行的每一条SQL语句自动提交,那就需要显性地开启一个事务。

START TRANSACTION;

3.2,回滚事务

在开启事务后,如果事务中的某些SQL语句出现异常情况时,就不能提交当前的事务,这时就需要使用ROLLBACK进行回滚事务操作。

ROLLBACK;

需要注意的是,ROLLBACK只能针对并未提交的事务进行回滚,已提交的事务无法进行回滚。当执行完ROLLBACK 或者 COMMIT后,当前事务才会自动结束。


3.3,提交事务

在开启事务后,每条SQL语句不再自动提交,用户需要使用COMMIT来手动进行提交,只有事务提交后,事务中的操作才能生效。

COMMIT;

3.4,事务的保存点

在回滚事务时,事务内所有的操作都会被撤销。如果我们希望只撤销一部分的数据,可以使用保存点来实现。

SAVEPOINT 保存点名;

在设置保存点后,使用以下命令可以完成将事务回滚到指定保存点。

ROLLBACK TO SAVEPOINT 保存点名;

如果使用时不再需要保存点,可以使用以下指令完成删除保存点操作。

RELEASE SAVEPOINT 保存点名;

值得一提的是,一个事务中可以创建多个保存点,在提交事务后,事务中的保存点就会被删除。

另外,在回滚到某个保存点后,该该保存点后创建过的保存点也都会消失。


3.5,事务自动提交

默认情况下,MySQL的提交方式是自动提交模式,也就是说用户执行的每一条SQL语句都会被当成一个单独的事务自动提交。

如果不想执行的每一条SQL语句自动提交,有两种操作方法。第1种,可以通过将该组的SQL语句作为一个事务;第2种,可以通过更改AUTOCOMMIT变量的值来实现,将其值设为1,表示开启自动提交,设为0,表示关闭自动提交。

若想要查看当前会话的AUTOCOMMIT值,使用以下语法:

SELECT @@autocommit;

image-20230122101021437

若想要关闭当前会话的事务自动提交,使用以下语法:

SET AUTOCOMMIT = 0;

image-20230122104140795

上述语法执行完后,当前会话的事务就不会自动提交了,需要我们手动进行提交操作,才会提交事务。

若直接终止MySQL会话,MySQL会对当前会话进行回滚操作。


3.6,事务访问模式

默认情况下,事务的访问模式为READ WRITE(读写模式),表示事务可以执行读(查询)或写(更改,插入,删除等)操作。

如果开发需要,可以将事务的访问模式设置为READ ONLY(只读模式),禁止对表进行更改操作。其更改语法:

SET [SESSION | GLOBAL] TRANSACTION READ ONLY;

如果想将事务的访问模式由只读模式恢复成读写模式,可使用以下语法:

SET [SESSION | GLOBAL] TRANSACTION READ WRITE;

3.7,事务操作注意

1,事务不允许嵌套,如果在执行START TRANSACTION语句前上一个事务还未提交,会隐式地执行提交事务的操作。

2,事务的处理主要是针对数据表中数据的处理,不包括创建或删除数据库,数据表,以及修改表结构等操作,而且执行这些操作时会隐式提交事务。

3,MySQL5.7默认的存储引擎为InnoDB,该引擎支持事务,而另外一个常见的存储引擎MyISAM却不支持事务。对于MyISAM存储引擎的数据表,无论事务是否提交,对数据的操作都会立即失效,不会回滚。

4,在MySQL中,还可以使用BEGIN来显式地开启一个事务,但由于BEGINBEGIN...END冲突,故不推荐使用BEIGN来开启事务。


4,隔离级别操作

数据库是一个多用户的共享资源,MySQL允许多线程并发访问,因此用户可以通过不同的线程来执行不同的事务,为了保证这些事务之间不相互影响,因此对事务设置隔离级。

4.1,查看隔离级别

对于事务的隔离级别查看,MySQL提供了以下几种不同的方式,具体使用哪种方式进行查询需根据具体需求进行选择。

#查看全局隔离级别
SELECT @@global.transaction_isolation;

#查看当前会话中的隔离级别
SELECT @@session.transaction_isolation;
  
#查看下一个事务的隔离级别
SELECT @@transaction_isolation;

全局的隔离级影响的是所有连接MySQL的用户;当前会话的隔离级别则只是影响当前正在登录MySQL服务器的用户,不会影响其他用户;而下一个事务的隔离级别仅对当前用户的下一个事务操作有影响。

在默认情况下,上述三种方式的返回结果都是REPEATABLE READ,表示隔离级别为可重复读。

image-20230122121954377


4.2,修改隔离级别

事务的隔离级别可以通过SET语句来进行修改事务的隔离级别。

#修改全局隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVER 参数值;

#修改当前会话中的隔离级别
SET SESSION TRANSACTION ISOLATION LEVER 参数值;
  
#修改下一个事务的隔离级别
SET TRANSACTION ISOLATION LEVER 参数值;

SET后的GLOBAL表示全局,SESSION表示当前会话,TRANSCATION表示事务,ISOLATION 表示隔离,LEVER表示级别。

参数值可以为READ UNCOMMITTED(读取未提交) READ COMMITTED(读取提交) REPEATABLE READ(可重复读) SERIALIZABLE(可串行化)

image-20230122125011875


5,事务并发问题

5.1,脏读

脏读就是指一个事务读取了另外一个事务还没有提交的数据。

脏读的流程示意图:

脏读的具体操作实例:

image-20230122133458799


5.2,不可重复读

不可重复读是指在一个事务中多次读取同一条记录,但先后读取到的数据却不同。

不可重复读的流程示意图:

不可重复读的具体操作实例:

image-20230122141942160


5.3,幻读

幻读是指在一个事务内先后两次查询中的数据记录数不一致。

按照特定条件查询数据时,没有对应的数据行,但是在插入数据时,又发现这行数据已经存在。

幻读是由于其他事务做了插入记录的操作,进而导致记录数有所添加。

幻读的流程示意图:

幻读的具体操作实例:

image-20230122144629693


6,事务隔离级别

隔离级别脏读不可重复读幻读
Read uncommitted✔️✔️✔️
Read committed✔️✔️
Repeatable Read(默认)✔️
Serializable

6.1,READ UNCOMMITTED

READ UNCOMMITTED表示读取未提交,是事务中最低的级别,在该级别下的事务可以读取到其它事务中未提交的数据,会出现脏读问题。

事务A和事务B的隔离级别为READ UNCOMMITTED,当事务A完成开启事务,和进行余额查询并对余额进行减少1000操作,但未提交事务,接着事务B在开启事务,进行查询余额操作,发现余额已经减少了1000,查询到的是事务A中修改后的余额数据,这种就是脏读。

image-20230122164531155

为了避免脏读情况的发生,可将客户端的事务隔离级设为READ COMMITTED(或更高级别的隔离级)来避免此类情况。

首先将事务B的隔离级修改为READ COMMITTED(或更高级别的隔离级),再按上述操作正常进行,发现事务B不会在读取到事务A未提交的数据记录了,从而不会出现脏读的情况了。

image-20230122170613111

注意:为了保证数据的一致性,该隔离级别在实际应用中几乎不使用。


6.2,READ COMMITTED

READ COMMITTED表示读取提交,是大多数DBMS(如SQL,Server,Oracle)的默认隔离级,但不包括MySQL。

在该隔离级别下,只能读取其它事务已经提交的数据,避免了脏读数据的情况,但这种情况下会出现不可重复读的问题。

事务A和事务B的隔离级别均为READ COMMITTED,当事务A完成开启事务和查询余额操作后,事务B就依次完成开启事务,查询余额,修改余额,提交事务等操作,紧接着在事务A中继续查询余额操作,发现在事务A中的先后两次的查询结果不同,这就是不可重复读问题。

image-20230122172003494

为了避免不可重复读情况的发生,可将客户端的事务隔离级设为REPEATABLE READ(或更高级别的隔离级)来避免此类情况。

首先将事务B的隔离级修改为REPEATABLE READ(或更高级别的隔离级),再按上述操作正常进行,发现事务A先后两次查询结果是相同的,说明REPEATABLE READ可以避免不可重复读的情况,从而不会出现不可重复读的情况了。

image-20230122174214331


6.3,REPEATABLE READ

REPEATABLE READ表示可重复读,是MySQL的默认事务隔离级,他解决了脏读问题和不可重复读问题。

其确保了同一事务的多个实例在并发读取数据时,会看到相同的结果,但在理论上会出现幻读的并发问题。

幻读和不可重复读有些类似,同样发生在两次查询过程中,不同的是,幻读是由于其他事务添加数据导致记录数有所增加。

MySQL的InnoDB存储引擎通过多版本并发控制机制解决了幻读的并发问题。

事务B的隔离级别为REPEATABLE READ,当客户端完成开启事务B,添加数据和提交事务的操作后,接着在另外一个客户端完成开启事务A,查询数据记录,发现无id为3的数据,但在插入id为3的数据时,发现无法插入,但查询时没有此数据,这就是幻读的情况。

image-20230122205603020
为了避免幻读情况的发生,可将客户端的事务隔离级设为SERIALIZABLE 来避免此类情况。


6.4,SERIALIZABLE

SERIALIZABLE表示可串行化,是MySQL中隔离级的最高级别,它在每个读取的数据行上加锁,使之不会发生冲突,从而解决了脏读、不可重复读和幻读的问题。

由于加锁可能导致超时和锁竞争现象,性能是4种隔离级中最低的。除非为了数据的稳定性,需要强制减少并发的情况时,才会选择此种隔离级。

事务B的隔离级别为SERIALIZABLE,当事务B完成开启事务和查询余额操作后,再让事务A进行开启事务和修改余额操作,会发现修改操作一直在等待,而不是立即就执行成功,这是因为事务B还未进行提交事务操作,等待事务B进行完提交事务操作。

image-20230122181420293

如果在事务A的更新操作等待时,提交事务B,事务A中的更新操作才会被执行,并提示执行结果:
在这里插入图片描述

如果事务B一直未进行提交事务的操作,事务A中的更新操作就会一直等待,直至超时后,出现如下提示:锁等待超时,尝试重启事务。

image-20230122195808900

在默认情况下,锁等待的超时时间是50秒,可以通过以下指令来查询:

SELECT @@innodb_lock_wait_timeout;

image-20230122200050854


结语

这就是本期博客的全部内容啦,想必大家已经对MySQL进阶中的事务的相关知识有了全新地认识和理解吧,如果有什么其他的问题无法自己解决,可以在评论区留言哦!

最后,如果你觉得这篇文章写的还不错的话或者有所收获的话,麻烦小伙伴们动动你们的小手,给个三连呗(点赞👍,评论✍,收藏📖),多多支持一下!各位的支持是我最大的动力,后期不断更新优质的内容来帮助大家,一起进步。那我们下期见!

在这里插入图片描述


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

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

相关文章

ORB SLAM3 ubuntu18.04 ROS 运行 段错误 (核心已转储) 踩坑及解决

问题猜测及解决:opencv版本兼容性 项目版本:ORB SLAM3 V1.0版本 CPU:13600K (大小核架构不知是否会影响) 电脑环境:ubuntu18.04 ROS运行 相机:D435 i opencv版本:3.2 and 4.6 前提:编译无报错&a…

Java 23种设计模式(3.创建者模式-原型模式)

1.概述 用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型对象相同的新对象。 2.结构 原型模式包含如下角色: 抽象原型类: 规定了具体原型对象必须实现的的 clone() 方法。 具体原型类: 实现抽象原型类的 clon…

多线程(5)

文章目录前言 :常见锁策略了1.悲观锁 VS 乐观锁2. 轻量级锁 VS 重量级锁3.自旋锁 VS 挂起等待锁4. 读写锁 VS 普通的互斥锁5. 公平锁 和 非公平锁6. 可重入锁 VS 不可重入锁CAS1. CAS 的应用场景2. CAS 的典型问题 : ABA 问题synchronized 原理1.锁升级 / 锁膨胀2.锁…

Ae 效果详解:发光

效果/风格化/发光Effects/Stylize/Glow发光 Glow效果可找到图像中的较亮部分,然后使那些像素和周围的像素变亮,以创建漫射的发光光环。可以创建两种颜色(颜色 A 和颜色 B )之间的渐变发光,并可通过复制发光效果以创建更…

RESTful开发风格 与 SpringMVC跨域访问

RESTful REST:表现层状态转换,资源在网络中以某种表现形式进行状态转移RESTful 是基于 REST理念 的一套开发风格,是具体的开发规则,如果一个架构符合REST 原则,就称为 RESTful 架构。 RESTful 开发规范:…

【leetcode】学了栈和队列却觉得无用武之地?试试这几道题目吧!

目录 0.写在前面 1.leetcode.20 有效的括号 2.leetcode.225 用队列实现栈 3.用栈实现队列 4.设计循环队列 0.写在前面 这些题目所用语言为C语言,由于C语言未提供栈和队列的数据结构,所以需要我们手动实现栈和队列。此外熟练掌握栈和队列的性质对解…

【C++】从0到1入门C++编程学习笔记 - 实战篇:职工管理系统

文章目录一、需求分析二、创建项目2.1 创建新项目2.2 添加文件三、创建管理类3.1 创建文件3.2 头文件实现3.3 源文件实现四、菜单功能4.1 添加成员函数4.2 菜单功能实现4.3 测试菜单功能五、退出功能5.1 提供功能接口5.2 实现退出功能5.3 测试功能六、创建职工类6.1 创建职工抽…

虚拟机克隆两网卡冲突

常见网卡设置 vim /etc/sysconfig/network-scripts/ifcfg-ens33TYPEEthernet BOOTPROTOstatic DEFROUTEyes NAMEens33 UUID025f7880-7357-4148-ae5a-a629d597c133 DEVICEens33 ONBOOTyes DNS18.8.8.8 IPADDR 192.168.100.16 GATEWAY192.168.100.254 NETMASK255.255.255.0有的版…

25/365 java 守护线程 线程同步 synchronized

1.守护线程 线程分为守护线程和用户线程 : daemon thread and non-daemon thread 虚拟机必须等待用户线程执行完毕,但无需等待守护线程执行完毕。 守护线程举例:垃圾回收线程,监控内存线程。 setDaemon(true):默认为false,默…

【LeetCode:121. 买卖股票的最佳时机~~~动态规划】

题目描述 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔交易中获取的…

【微信小程序】文章点赞功能的实现

🏆今日学习目标:第二十期——文章点赞功能的实现 ✨个人主页:颜颜yan_的个人主页 ⏰预计时间:15分钟 🎉专栏系列:我的第一个微信小程序 文章目录前言效果图实现步骤总结前言 哈喽大家好,本期是…

Unity简单几行代码让玩家水平移动更丝滑真实

可以先来看看基础的移动代码,接收玩家的输入,然后赋予刚体速度。 但是这种写法存在几个问题,下面一一纠正。 首先,如果直接改变刚体的速度,那么可能会出现穿墙的问题。 而且没有一种从速度0到缓慢加速的过程&#xff…

自定义Filter后,我的业务代码怎么被执行了多次?

若要求构建的过滤器针对全局路径有效,且无任何特殊需求(主要针对 Servlet 3.0 的一些异步特性),则完全可直接使用 Filter 接口(或继承 Spring 对 Filter 接口的包装类 OncePerRequestFilter),并…

分享130个ASP源码,总有一款适合您

ASP源码 分享130个ASP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下..., 130个ASP源码下载链接:https://pan.baidu.com/s/13ZxaHPHdgorjGV1wWvx1WQ?pwd7z4p 提取码&#x…

07_FreeRTOS任务调度器的挂起和恢复

任务调度器的挂起和恢复 挂起任务调度器,调用此函数不需要关闭中断 使用格式示例: 1.与临界区不一样的是,挂起任务调度器,未关闭中断; 2.它仅仅是防止;饿任务之间的资源争夺,中断照样可以直接响应; 3.挂起调度器的方式,适合于临界区位于任务与任务之间;既不用去延…

MySQL 8.0.31 集合操作INTERSECT和EXCEPT

对于聚合的功能MySQL是都是默默的发展。在最新的8.0.31版本中提供对集合操作INTERSECT和EXCEPT。这样一来,集合操作功能基本圆满了。MySQL5.7.40版本是不支持这个集合的。 In this release MySQL adds support for the SQL standard INTERSECT and EXCEPT table op…

Linux常用命令——ssh命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) ssh openssh套件中的客户端连接工具 补充说明 ssh命令是openssh套件中的客户端连接工具,可以给予ssh加密协议实现安全的远程登录服务器。 语法 ssh(选项)(参数)选项 -1:强制使用ssh协…

基于FPGA的时间数字转换(TDC)设计(四)

1. 基于IODELAY的TDC设计原理 在第一篇中讲过,基于FPGA开发的TDC常见的有直接计数法,多相位时钟采样法,抽头延迟线法等等。前面3篇讲解了基于多相位的TDC,接下来主要讲解基于抽头延迟线的方法。在Xilinx FPGA开发中,要实现抽头延迟线,主要由进位链(Carry4)和IODELAY模块…

寒假题练——day(6)

题目1: 有一种兔子,从出生后第3个月起每个月都生一只兔子, 小兔子长到第三个月后每个月又生一只兔子。 例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。 一月的时候有一只兔子,假如兔…

检索方案优化

文章目录 1. Flab框架概览2. Flab框架各个层在基金检索的具体应用2.1. 前置检查Check层2.2. 多路召回Recall层2.3. 结果集过滤2.3.1. 问财和我们召回结果的交集2.4. 排序Rank2.5. 缓存Cache2.6. 封装Assmeble1. Flab框架概览 Fly like a bird 寓意灵活 2. Flab框架各个层在基金…