当前位置: 首页 > backend >正文

MYSQL 认识事务

文章目录

  • 认识事务
    • 数据库的并发问题
      • 什么是数据库的并发问题?
      • 数据库的并发问题由谁负责解决?
      • 对数据库的增删查改操作,如果不加锁,会出现怎样的问题?
      • 请问对数据库的增删查改操作,应该如何处理,才能解决上面的问题?
    • 什么是事务?
      • 教科书版本
      • 举例理解:
        • 例子1
        • 例子2
      • 为什么要引入事务这个概念?
      • 有哪些存储引擎支持事务?
    • 事务的四个核心属性(ACID)
    • 如何理解事务的一致性
      • 一致性的定义
      • 如何确保一致性?
      • 常见的一致性破坏场景与规避方案
      • 理解一致性的3个关键
      • 总结
        • mysql没有为一致性做任何工作
        • mysql针对一致性做了很多工作
    • 事务的提交方式
      • 什么是事务的提交?
      • 什么叫做事务自动提交?
      • 什么叫做事务手动提交?
      • 如何查看mysql的事务提交方式?
      • 如何更改mysql的事务提交方式?
    • 事务的操作方式(验证事务的原子性和持久性)
      • 实验环境搭建
      • 演示正常的事务回滚
      • 演示事务一旦提交,MySQL数据就已经持久化保存了
      • 验证如果事务还没有来得及提交,客户端就崩溃了,刚刚未提交的数据不会被数据库保存
      • 验证事务一旦提交,即使客户端崩溃,MySQL数据也都不会受影响,已经持久化
      • 对比实验,验证begin操作会自动将提交方式修改成手动操作,不会受MySQL是否自动提交影响
        • (1)有begin操作的自动提交组
        • (2)无begin操作的手动提交组
        • (3)无begin操作的自动提交组
        • 实验结论
      • 手动提交与自动提交
        • 如何实现手动提交?
        • 如何实现自动提交
        • autocommit=on的含义
        • begin的含义
        • begin开启事务之后,在命令行中输入多条sql语句,然后再commit提交,与autocommit=on的状态下直接在命令行中输入这多条sql语句有什么区别?
      • 手动回滚与自动回滚
        • 事务可以手动回滚吗?
        • 那事务可以自动回滚吗?
        • 事务自动回滚的具体场景有哪些呢?
          • 1. **SQL语句执行失败(语法错误或约束冲突)**
          • 2. **数据库连接异常中断**
          • 3. **事务超时被数据库终止**
          • 4. **数据库进程异常终止**
        • 如果没有设置保存点,还能回滚吗?
        • 如果一个事务被提交了(commit),还能回退吗?(rollback)
        • commit之前,可以指定回退到哪个保存点吗?
        • 是不是MYSQL所有的存储引擎都支持事务呢?InnoDB 支持事务吗? MyISAM 呢?
        • 开始事务的指令是?

认识事务

数据库的并发问题

什么是数据库的并发问题?

数据库本身是会被大量的请求所访问的,但是数据库中的索引和数据却只有一份,那么多个请求在同时访问数据库的时候就会存在着进程并发的问题,即多线程/进程同时访问一份临界资源,导致数据不一致的问题

数据库的并发问题由谁负责解决?

现在请问这个并发的问题谁来解决?是Mysql自己解决,还是交给上层用户自己解决?
如果交给上层用户,那就是给每个上层用户都增加了工作量,这是大家不太愿意接受的。所以这个任务显然是只能交给Mysql自己解决。那mysql是如何解决这个并发问题的呢?

大致的方案有两种

  • 一种方案是,mysql就只做一个进程,不做多进程,所有的请求都交给这一个进程处理
  • 还有一种方案就是多线程,每一个请求都分配一个线程专门处理

对数据库的增删查改操作,如果不加锁,会出现怎样的问题?

就是我们前面说过的数据不一致问题
在这里插入图片描述

请问对数据库的增删查改操作,应该如何处理,才能解决上面的问题?

  • 首先你买票的过程得是原子的吧(原子性)
  • 然后你买票不能相互影响吧(隔离性)
  • 买完票应该要永久有效吧(永久性)
  • 买前,和买后都要是确定的状态吧(一致性)

什么是事务?

教科书版本

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

举例理解:

例子1

一件事务,其实就对应你上层应用程序的一项业务
一件事务,往往由多条sql语句组成(事务:sql语句 = 1 :n)
比如我给你转钱,这是一件事务,我具体完成的时候,需要先查看我包里有多少钱,从我包里拿出这些钱,把这些钱交给你。

例子2

事务就是要做的或所做的事情,主要用于处理操作量大,复杂度高的数据。
假设一种场景:你毕业了,学校的教务系统后台 MySQL 中,不再需要你的数据,要删除你的所有信息, 那么具体来说就是,既要删除你个人的基本信息(姓名,电话,籍贯等)(在students这张表中,把你的表项删了),也要删除和你有关的其他信息,比如:你的各科成绩,你在校表现,甚至你在论坛发过的文章等(在所有表中删除与你有关的表项)。这样,就需要多条 MySQL delete语句构成,那么所有这些操作合起来,就构成了一个事务。

为什么要引入事务这个概念?

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

有哪些存储引擎支持事务?

只有innodb支持
具体可以在命令行输出show engines\G;查看验证

事务的四个核心属性(ACID)

一个事务,可不可以简单理解成sql语句的集合呢?为什么?如果不能,还需要些什么?
不能,一个事物除了要多条包含sql语句,还需要包含一套机制控制这些语句按序执行
所有,一个完整的事务,绝对不是简单的 sql 集合,还需要满足下面的四个核心属性,通常被称为事务的 ACID 特性,它们是数据库事务处理的基础,确保数据操作的可靠性和正确性。这四个属性分别是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。

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

  2. 一致性:

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

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

如何理解事务的一致性

一致性的定义

在我们前面列举的事务特性中,唯独一致性这一条,我们没有做解释。因为他似乎没办法简单用一两句话来解释。教材就试图用一两句话来解释一致性,它的话是这样的:

在事务开始之前和事务结束以后,数据库的完整性没有被破坏。
这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。

是不是读完之后感觉还是不太清楚?既然一两句话解释不清,那我们就详细说说

要理解事务的一致性,需要先明确其定义边界——它并非孤立存在,而是与事务的原子性(Atomicity)、隔离性(Isolation)、持久性(Durability)紧密联动,最终确保数据从“合法初始状态”经过事务执行后,仍处于“合法目标状态”,且整个过程中数据不会出现“逻辑矛盾”或“规则破坏”。

事务的一致性,本质是数据的“合法性约束”在事务执行前后不被破坏。这里的“合法性”由业务规则、数据逻辑或数据库约束(如主键、外键、唯一索引、CHECK约束等)定义,核心是要确保数据不能处于逻辑上的中间态或错误态

读到这里初学者可能还是不太清楚。因为还是有一堆问题,比如什么叫做逻辑上的中间态和错误态?什么叫做数据的合法性约束? 下面就来举个最直观的例子:
假设A账户有1000元,B账户有500元,现在执行“A向B转账200元”的事务。

  • 初始合法状态:A=1000,B=500,总余额=1500;
  • 事务执行逻辑:A减少200(A=800)、B增加200(B=700);
  • 目标合法状态:A=800,B=700,总余额仍=1500。

在上面的过程中,总余额=1500就是数据的合法性约束,事务执行前后总余额都是1500,这就叫做数据的合法性约束在事务执行前后不被破坏

如果事务执行后出现以下情况,就是一致性被破坏

  1. A减少200但B没增加(A=800,B=500,总余额=1300,违反“总余额不变”的业务规则);
  2. A没减少但B增加200(A=1000,B=700,总余额=1700,同样违反总余额规则);
  3. A减少300但B只增加200(A=700,B=700,总余额=1400,数据逻辑矛盾)。

像上面这三种情况,总余额不等于1500,就称为逻辑上的中间态或错误态。为啥这么说呢?你可以这么理解,A向B转账200元,在计算机内做的操作就是A的账户余额减二百,B的账户余额加200,这俩步骤肯定是有先有后,不可能同时执行。那一定存在着某个时刻,这个时刻A已经减200了,但B还没加200,这个时刻就是逻辑上的中间态,因为事务还没执行完,B的200块还没到账呢呀。现在你事务正在执行中,数据处于中间态无可厚非,但你要是事务执行完毕时,还处于这种状态,那就是错误态了

如何确保一致性?

一致性并非孤立存在,而是依赖原子性、隔离性、持久性的“协同支撑”——缺少任何一个特性,一致性都无法保障。三者与一致性的关系如下:

ACID特性核心作用对一致性的支撑
原子性(Atomicity)事务“要么全执行,要么全回滚”,不允许部分执行避免“事务部分成功”导致的数据中间态(如转账只扣A的钱,不增B的钱)
隔离性(Isolation)多个事务并发执行时,相互不干扰(如避免“脏读”“不可重复读”)防止并发事务修改同一数据导致的逻辑冲突(如两个事务同时扣减同一商品库存,导致库存负数)
持久性(Durability)事务提交后,数据修改永久生效(即使数据库崩溃)避免“事务提交后数据丢失”导致的一致性破坏(如下单后数据库崩溃,订单记录丢失,库存却已扣减)

总结:原子性保障“事务内部无中间态”,隔离性保障“事务之间无干扰”,持久性保障“事务结果不丢失”——三者共同为一致性搭建了“防护网”。

常见的一致性破坏场景与规避方案

在实际开发中,一致性破坏多源于“事务设计缺陷”或“并发控制不当”,以下是典型场景及规避方法:

一致性破坏场景根本原因规避方案
转账后“钱消失”或“钱变多”事务未包含“扣减付款方”和“增加收款方”两个操作,或未使用原子性(部分执行后未回滚)1. 将两个操作纳入同一个事务;
2. 事务执行失败时强制回滚(依赖原子性)
电商超卖(库存为0仍能下单)并发事务未隔离,多个事务同时读取“库存=1”并扣减,最终库存变为-11. 使用数据库行锁(如MySQL的SELECT ... FOR UPDATE)锁定库存记录;
2. 采用乐观锁(如版本号机制)避免并发修改冲突
订单金额计算错误(金额≠单价×数量)事务未包含“计算订单金额”的逻辑,或步骤顺序错误(先创建订单,后修改商品单价)1. 事务中先确认商品单价,再计算订单金额(订单金额=单价×数量);
2. 订单创建后,商品单价修改不影响已创建订单(通过“订单表存储下单时的单价”实现)
事务提交后数据丢失(如订单记录丢失)事务未确保持久性(如未等待数据库落盘就返回成功)1. 使用数据库的“事务提交确认机制”(如MySQL的innodb_flush_log_at_trx_commit=1,确保事务日志实时落盘);
2. 关键业务(如订单、支付)增加“数据校验机制”(如定时核对订单数与库存扣减数)

理解一致性的3个关键

  1. 核心是“合法性”:一致性的本质是“数据符合业务规则和数据约束”,而非“数据值不变”;
  2. 依赖多层保障:数据库级约束保障基础逻辑,业务级设计保障复杂规则,ACID其他特性保障执行过程;
  3. 规避核心是“无中间态、无并发冲突、无结果丢失”:通过原子性避免部分执行,通过隔离性避免并发干扰,通过持久性避免结果丢失。

总结

mysql没有为一致性做任何工作

前面的原子性,还有后面的隔离性和持久性,mysql为了实现这些性质,创建了很多的数据结构和算法,但是Mysql 并没有专门为了实现一致性而设计任何的数据结构和算法

mysql针对一致性做了很多工作

一致性是结果!
mysql通过创建数据结构和算法,实现了事物的原子性、隔离性、持久性,这三点再加上程序员的努力,最终实现了一致性

事务的提交方式

什么是事务的提交?

你一个事务不是包含多个sql语句,要对数据做各种操作吗,那我现在请问你,mysql执行了这一系列的操作之后,是不是有一个执行的结果,即成功或失败

  • 如果这些操作都执行成功了,我就将操作涉及到的数据进行对应更新
  • 如果这些操作没有完全执行成功,我要将那些改一半的数据回退,恢复成改之前的样子

像这样,事务执行结束以后,将事务中对数据库所做的修改永久保存到数据库的操作,就叫做事务的提交

什么叫做事务自动提交?

就是mysql执行完这一系列的指令之后,自动将执行结果提交给数据库,更新对应的数据

什么叫做事务手动提交?

就是mysql执行完这一系列的指令之后,由用户手动输入提交命令,将执行结果提交给数据库,更新对应的数据

如何查看mysql的事务提交方式?

命令行输入:mysql> show variables like ‘autocommit’;
在这里插入图片描述

如何更改mysql的事务提交方式?

用 SET 来改变 MySQL 的提交模式:
比如我们可以在mysql命令行中输入set autocommit=0;将提交方式改成手动提交
在这里插入图片描述

命令行输入set autocommit=1;将提交方式改成自动提交
在这里插入图片描述

事务的操作方式(验证事务的原子性和持久性)

事务的操作方式有哪些?

实验环境搭建

首先我们先创建一个测试表
在这里插入图片描述

为了便于演示,我们在创建表之后通过set global transaction isolation level READ uNcoMMITTED; 指令将mysql的默认隔离级别设置成读未提交
在这里插入图片描述

我们开两个终端,同时登录mysql,模拟mysql被并发访问的情况
两个终端同时进入数据库101_db
在这里插入图片描述

演示正常的事务回滚

事务的常规操作一共有以下五种
在这里插入图片描述

首先我们重新登入mysql,在命令行输入start transaction; 或者begin;表示开启一个事务
在这里插入图片描述

注意:无论你之前设置的事务提交方式是手动提交还是自动提交,只要你用begin或者start transaction开启一个事务,到后面你必须输入commit指令手动提交
从此往后我们后续的指令执行结果都不会被提交到数据库,直到我们输入commit,词汇将这个事务提交上去

然后我们创建一个保存点:

mysql> savepoint save1;
Query OK,0rows affected (O.00 sec)

向表中插入一条数据

mysql>insert into account values(1'张三'1oo);
Query OK,1 row affected (O.05 sec)

然后我们再创建一个保存点

mysql> savepoint save2;
Query OK,0rows affected (O.01 sec)

再插入一条记录

mysql> insert into account values(2'李四'10000);
Query OK,1 row affected (O.00 sec)

现在查看表中数据,发现两条记录都在表中

mysql> select * from account;
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
|  1 | 张三   |    100.00 |
|  2 | 李四   | 10000.00 |
+----+--------+----------+
2 rows in set (0.00 sec)

现在我们回滚到上一个保存点

mysql> rollback to save2;
Query OK,0 rows affected CO.03sec)

发现第二次插入的记录就没有了

mysql> select * from account;
+----+--------+----------+
| id | name   | blance   |
+----+--------+----------+
|  1 | 张三   |    100.00 |
+----+--------+----------+
1 row in set (0.00 sec)

直接回滚到最开始

mysql> rollback;
Query OK,0 rows affected (O.00 sec)

发现刚刚的记录全没有了

mysql> select * from account;
Empty set CO.00 sec)

演示事务一旦提交,MySQL数据就已经持久化保存了

现在我插入两条数据之后,将事务提交


mysql> select * from account;
Empty set (0.00 sec)mysql> insert into account values (1, '张三', 200);
Query OK, 1 row affected (0.00 sec)mysql> insert into account values (2, '李四', 200);
Query OK, 1 row affected (0.00 sec)mysql> select * from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 200.00  |
|  2 | 李四   | 200.00  |
+----+--------+---------+
2 rows in set (0.00 sec)mysql> commit;
Query OK, 0 rows affected (0.00 sec)

我们在另一终端登录mysql,打开这个数据库,再次查看account表中的信息,发现刚刚插入的数据已经躺在里面了,即使我调rollback之后,数据仍在里面保存着

mysql> select * from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 200.00  |
|  2 | 李四   | 200.00  |
+----+--------+---------+
2 rows in set (0.01 sec)mysql> rollback;
Query OK, 0 rows affected (0.00 sec)mysql> select * from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 200.00  |
|  2 | 李四   | 200.00  |
+----+--------+---------+
2 rows in set (0.00 sec)

验证如果事务还没有来得及提交,客户端就崩溃了,刚刚未提交的数据不会被数据库保存

如果当前事务的隔离性是读未提交(Read Uncommitted),那么在一端向数据库中插入数据的操作提交之前,另一端也可以看到刚刚插入的数据

比如在下图中,我现在在左端开启了一个事务,执行了一次表单的插入操作,但没有提交,此时右端也能同步地看到刚刚修改过后的数据
在这里插入图片描述
我现在在左端开启事务之后,又进行了一次表单的UPDATE操作,然后也没有提交,此时另一端也能同步地看到刚刚修改过后的数据,即王五的blance被改成了500块
在这里插入图片描述

现在我突然关掉左边这个刚刚执行插入和修改操作的mysql客户端(注意,此时我还没有提交数据,但这个客户端就异常退出了),请问另一端查看该数据库中的数据会有什么变化呢?看到的数据是提交之前的数据,还是提交之后的数据呢?

下图就是右端mysql客户端在左端退出前后进行的两次查询操作
在这里插入图片描述

答案非常清楚了,左端提交之前退出,右端再查看到的就是修改之前的数据,只要左端最后事务没提交,数据库就不会更新。即数据库不会更新未提交的数据,数据库中的数据信息与修改前保持一致

验证事务一旦提交,即使客户端崩溃,MySQL数据也都不会受影响,已经持久化

下面我们让左端客户端在事务提交之后异常 退出
在这里插入图片描述

退出之后,在另一个终端上查看表中数据,可以看到刚刚提交上去的数据已经被保存了
在这里插入图片描述

对比实验,验证begin操作会自动将提交方式修改成手动操作,不会受MySQL是否自动提交影响

(1)有begin操作的自动提交组

进去之前我们先将mysql的事务提交方式设置成自动提交
在这里插入图片描述

然后我们这边begin开启事务,插入一条数据之后abort异常终止,注意:如果这时候是事务提交方式是自动提交,那么无需我手动输出commit,刚刚的修改操作就会自动提交到mysql
在这里插入图片描述

但事实却是,程序异常终止后,修改的操作并没有保存到数据库,这说明此时事务提交方式并不是自动提交,而是手动提交

在这里插入图片描述

(2)无begin操作的手动提交组

将事务提交方式改成手动提交,然后不输入begin直接Insert
在这里插入图片描述

然后我插入端直接abort退出(注意,这个端口既没有begin也没有commit),然后我们在另一端查看刚刚插入的数据有没有同步到数据库中(结果会怎样呢?)
在这里插入图片描述

结果发现刚刚插入的赵六不见了

(3)无begin操作的自动提交组

现在我们再次打开左端的数据库,事务提交方式改成自动提交,不输入begin,直接向刚刚表中再插入一条赵六的信息,然后abort退出(注意这次操作,我们没有begin也没有commit),结果会怎样呢?

在这里插入图片描述
结果发现刚刚插入的赵六还在

实验结论

默认情况下,每一条sql,都会自动被mysql封装成为事务!!如果事务的提交方式是自动提交,即autocommit ON,mysql在每条sql语句执行之后对当前事务做自动提交,其中如果用begin / commit,mysql会自动转为手动提交

手动提交与自动提交

在上一个章节中,我们仅仅是介绍了手动提交与自动提交的概念,下面我们要结合实践,对其有一个更深入的认识

如何实现手动提交?

当autocommit=off时

mysql> UPDATE account SET balance = balance - 100 WHERE name = '张三';
mysql> UPDATE account SET balance = balance + 100 WHERE name = '李四';
mysql> COMMIT;

当autocommit=on时

mysql> BEGIN; -- 明确开启事务
mysql> UPDATE account SET balance = balance - 100 WHERE name = '张三';
mysql> UPDATE account SET balance = balance + 100 WHERE name = '李四';
mysql> COMMIT;
如何实现自动提交

首先我们要开启自动提交模式:

SET autocommit = 1; -- 开启自动提交

然后直接输指令就行。开启autocommit之后,你的每条指令都会被自动封装为一个事务。每输一条指令,它都会帮我们这条指令对应的事务自动提交

autocommit=on的含义

当autocommit设置为on时,每一条 SQL 语句都会被当作一个独立的事务来执行。一旦这条 SQL 语句执行成功,所做的更改会立即永久性地保存到数据库中,就如同对这条 SQL 语句隐式地执行了COMMIT操作。

autocommit=on最大的作用是让我们单条语句执行起来更加方便。举个例子:
假如说我们只想向数据库中插入一条新数据

如果autocommit=off,我们需要:

  1. 先在sql命令行中输入begin开启一个事务
  2. 然后再向sql命令行中输入sql语句insert into ...
  3. 最后还需要在sql命令行中输入commit提交这个事务

而如果autocommit=on,我们只需要向sql命令行中输入sql语句insert into ...即可

begin的含义

这个指令就是在autocommit=on的状态下,告诉后台,我接下来提交的多条sql语句都是同一个事务的,你不能再输一句提交一次了,你必须等我输入commit指令之后,把我前面输的所有sql语句当做一个事务提交

当然这个指令在autocommit=off状态下也能正常使用,表示一个事务的开启,但是在autocommit=off状态下,即使你不输入begin,MySQL 也会将 “第一条 SQL 语句(如INSERT/UPDATE/DELETE)” 作为事务的起点,无需手动执行BEGIN。此时:

  • 所有后续 SQL 语句会被纳入当前事务,直到执行COMMIT(提交)或ROLLBACK(回滚);
  • 提交 / 回滚后,下一条 SQL 语句会自动开启新的事务(依然无需BEGIN)。
begin开启事务之后,在命令行中输入多条sql语句,然后再commit提交,与autocommit=on的状态下直接在命令行中输入这多条sql语句有什么区别?

第一种方式,这多条sql语句属于同一个事务,要么一起被执行,要么都不被执行。而第二种方式,这多条sql语句每一条都是一个单独的事务,彼此的执行都是独立的,可能出现第一条和第三条执行成功了,但是第二条执行失败了的情况

手动回滚与自动回滚

事务可以手动回滚吗?

当然可以,我们可以通过rollback指令直接回退到事务最开始,也可以通过rollback to + 保存点;指令回退到指定保存点

那事务可以自动回滚吗?

当事务无法正常完成(出现中断或错误)时,数据库会自动撤销所有未提交的修改,自动回滚到事务最开始,确保一致性。

事务自动回滚的具体场景有哪些呢?
1. SQL语句执行失败(语法错误或约束冲突)

当事务中某条SQL语句执行出错(如语法错误、违反主键/外键约束、数据类型不匹配等),数据库会自动回滚当前事务中所有已执行的操作,确保不会留下“部分成功”的中间态。

示例

SET autocommit = 0;
BEGIN;
UPDATE account SET balance = balance - 100 WHERE name = '张三'; -- 执行成功(暂存)
UPDATE account SET balance = balance + 'abc' WHERE name = '李四'; -- 语法错误(字符串不能加给数字)
-- 第二条SQL失败后,数据库自动回滚第一条的修改,张三余额恢复原值
2. 数据库连接异常中断

若事务执行过程中,客户端与数据库的连接意外断开(如网络故障、客户端进程崩溃、强制关闭连接等),数据库会检测到“连接丢失”,自动回滚该连接上所有未提交的事务。

示例

  • 转账时,已执行“扣张三钱”但未执行“加李四钱”,此时客户端突然崩溃,数据库会自动回滚“扣张三钱”的操作,避免数据不一致。
3. 事务超时被数据库终止

部分数据库(如MySQL)可设置事务超时时间(innodb_lock_wait_timeout等参数),若事务持有锁时间过长(阻塞其他事务),数据库会强制终止该事务并自动回滚。

示例

  • 事务A长时间未提交且持有某行锁,导致事务B等待超时,数据库可能终止事务A并回滚其操作,释放锁资源。
4. 数据库进程异常终止

若数据库服务(如mysqld进程)意外崩溃或被强制关闭,重启后会通过“事务日志(Undo Log)”自动识别并回滚所有崩溃前未提交的事务,确保数据恢复到崩溃前的一致状态。

如果没有设置保存点,还能回滚吗?

如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback指令回滚即可

如果一个事务被提交了(commit),还能回退吗?(rollback)

如果一个事务被提交了(commit),则不可以回退(rollback)

commit之前,可以指定回退到哪个保存点吗?

可以,输入指令rollback to + 保存点的名字;

是不是MYSQL所有的存储引擎都支持事务呢?InnoDB 支持事务吗? MyISAM 呢?

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

开始事务的指令是?

start transaction 或者 begin

http://www.xdnf.cn/news/19567.html

相关文章:

  • 大数据生态系统全景图:Hadoop、Spark、Flink、Hive、Kafka 的关系
  • three.js手机端的4种旋转方式
  • 优秀开源内容转自公众号后端开发成长指南
  • Java-114 深入浅出 MySQL 开源分布式中间件 ShardingSphere 深度解读
  • Linux 文本处理实战手册
  • 销售事业十年规划,并附上一套能帮助销售成长的「软件工具组合」
  • 爬虫实战练习
  • C 基础(1) - 初识C语言
  • 2025年数字化转型关键证书分析与选择指南
  • compile_commands.json 文件详解
  • Linux基础2
  • (3dnr)多帧视频图像去噪 (一)
  • GDAL 简介
  • C++ multiset数据结构的使用情况说明
  • 基于单片机智能饮水机/智能热水壶
  • 正式发布!2025AI SEO公司哪家专业?
  • 【数据分享】多份土地利用矢量shp数据分享-澳门
  • C# FlaUI win 自动化框架,介绍
  • 员工自愿放弃社保,企业给补贴合法吗?
  • Vue3 中 Proxy 在组件封装中的妙用
  • Windows 使用 Compass 访问MongoDb
  • 【HarmonyOS】一步解决弹框集成-快速弹框QuickDialog使用详解
  • 笔记:现代操作系统:原理与实现(1)
  • 卷积神经网络中的两个重要概念——感受野receptive filed和损失函数loss function
  • 【Element Plus `el-select` 下拉菜单响应式定位问题深度解析】
  • 刘洋洋《一笔相思绘红妆》上线,献给当代痴心人的一封情书
  • CUDA编程11 - CUDA异步执行介绍
  • Java 不支持在非静态内部类中声明静态 Static declarations in inner classes are not supported异常处理
  • elasticsearch中文分词器analysis-ik使用
  • Uniapp 生命周期详解:页面生命周期 vs 应用生命周期(附实战示例)