前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >初识MySQL · 事务 · 上

初识MySQL · 事务 · 上

作者头像
_lazy
发布2025-06-13 11:01:40
发布2025-06-13 11:01:40
5800
代码可运行
举报
文章被收录于专栏:Initial programmingInitial programming
运行总次数:0
代码可运行

前言:

前文我们介绍了MySQL中的索引,通过磁盘引出MySQL与磁盘交互的基本单位是16KB,而对于16KB来说它是一个结构体,并且在Innodb存储引擎里面是通过B+树的形式进行管理的,那么具体的细节内容各位可移步上文阅读。

在本文,我们要介绍的是MySQL中的另一个非常重要的特性:事务,那么本文介绍事务将从生活中的实际例子引出事务,再到什么是事务,事务的基本特性是什么,通过实际的sql语句操作,介绍事务中的不同特性。

那么废话不多说,我们直接进入主题吧!


生活例子

生活中对于买票的场景是非常常见的,而这本质上是对数据库进行操作,如果对数据库的CURD操作不进行任何限制,那么就会导致出现上述的情况。

当A客户端A执行卖票的时候,此时票的数量还没有减少,那么刚好客户端B此时判断票的数量是大于0的,那么也直接执行卖票的操作,此时两个都买到票了,然后执行票数量的更新,就会导致一张票被重复卖了两次,甚至可能会出现票的数量走到了-1 -2的情况。

那么以上的情况在实际买票的时候是绝对不允许的,所以,对数据的CURD操作一定要有某种特性来解决上述的问题,特性大致可以分为:买票的过程是原子的,买票互相应该不能影响,买完票的前后状态应该是永久的,买票之后的票应该是永久有效的

那么我们带着这样的认识,来走进MySQL中的事务。


什么是事务

直接给结论:事务实际上就是一组SQL语句,这组SQL语句在逻辑上有一定的连贯性。而我们常说的执行事务成功就是该组语句全部执行成功,要么就全部失败,因为它们被打包成了一个事务,由于事务的执行是原子性的,所以要么全成功要么全失败。

那么上述的生活例子,我们可以将检测数量,买票,更新这三条语句打包为一个事务,打包为了事务之后,满足四个特性,那么就能避免票重复卖的问题。

所以现在我们得出了一个结论:MySQL中的事务实际上就是一组SQL语句,因为是一组,一条语句也可以单独为组,所以事务中的SQL语句至少大于等于1条。

我们由生活中的例子举例出来的四种特性,实际上用官方话语来说应该是:原子性,隔离性,持久性,一致性。介绍事务也主要是围绕这四个特点介绍的。

对于原子性来说,表示的是这个事务执行情况要么是全成功要么是全失败,而在MySQL中为了保证原子性,引入了回滚机制,这也是MySQL的事务比Redis的事务难的一个点。在MySQL中,原子性是通过Undo Log(回滚日志)实现的,在事务出错时可以回退所有已执行的操作。 对于隔离性来说,因为MySQL中肯定是会同时存在大量的事务的,大量的事务之间的读写操作是不能影响到别的事务的读写操作,那么这个影响程度就很有说法了,根据影响程度的不同,我们将隔离级别分为了四种:读未提交,读已提交,可重复读,串行化。不同的隔离性有不同的表现,我们后续介绍。 对于持久性来说,表示的是事务结束,也就是一组SQL语句执行完毕之后,对数据的修改就是永久的,即便系统故障了也不会丢失,这就是持久性。MySQL 通过 redo log(重做日志) 来保证持久性,确保在崩溃恢复时数据不会丢失。 对于一致性来说,是指事务执行前后,数据库要从一个合法状态转换为另一个合法状态,不违反约束(如外键、唯一性、业务规则等)。它是这四个特性中最难理解的一点,一致性更像是一种符合预期的特点,比如我们完成了转账的操作之后,对方账户多了5000块钱,我们的账户减少了5000块钱,并且其他数据都是正常的,那么也就符合我们的心理预期。

上述的四个属性,简称为ACID,即Atomicity,Consistency,Isolation,Durability,当然我们不用刻意的记。

为什么要有事务

上述说了那么多事务的特性,那么为什么需要事务呢?实际上,使用事务是为了保证数据的完全无误。

比如通过原子性,我们能够避免在实际操作中的中间态,从而避免由于中间态导致的一系列后果,比如通过隔离性,我们能够解决由于高并发导致的脏读,幻读,不可重复读等问题,比如通过持久性,我们能保证数据的永久性。事务就是为了让数据库在“多人并发、程序出错、突然宕机”等复杂情况下,依然保持数据的完整性、一致性和可靠性

事务的版本支持

对于MySQL来说,它只有使用了Innodb数据库引擎的数据库或表才支持事务,像MyISAM 就不支持,我们可以通过show engines \G查看数据库引擎:

Transactions代表的就是事务,InnoDB的Comment解释了说支持事务,外键,以及锁机制,对于其他引擎来说都是不支持的。


事务操作

事务的提交

对于事务的提交有两种方式,一种手动提交,一种是自动提交,查看事务提交方式:

那么我们可以通过SET来改变MySQL的自动提交方式:

那么同理,设置为1就代表的是ON,0就代表的是OFF。

那么事务的手动提交和自动提交是否会影响到我们后面的呢,先埋下一个伏笔。

事务的操作

在进行事务操作之前,我们先将事务的隔离级别设置为读未提交,为了方便测试,但是在实际的场景中,几乎是不会使用到这种隔离场景的,那么设置为读未提交是:

代码语言:javascript
代码运行次数:0
运行
复制
set global transaction isolation level read uncommitted;

可以通过SELECT @@transaction_isolation查看隔离级别,而在5.7可以使用tx_isolation,但是在8.0之后已经废弃了tx_isolation:

可以看到目前的隔离级别是读未提交,然后我们可以准备一张测试表:

代码语言:javascript
代码运行次数:0
运行
复制
create table test_tx( id int primary key, name varchar(20) not null );

事务的开始和回滚

事务开始可以使用begin和start transaction,这里为了演示我们启动两个终端:

并且表中也是没有任何数据的,我们根据实际不同的场景来演示。

正常场景

第一个结论,在隔离状态为读未提交的情况下,我们往表中插入数据之后,两个事务同时在运行,但是另一个事务也能看到结果,并且这个时候左侧事务还没有提交。此时我们将左侧事务提交之后:

左侧提交之后,右侧的事务也不出意外的能够看到了。这是第一个隔离性的开胃菜。

回滚机制

对于MySQL中最重要的回滚机制涉及的命令是:savepoint和rollback to。savepoint表示的是创建回滚点,rollback to表示的是回滚到哪个回滚点。现在我们将表清空之后实验。

创建好了之后,我们尝试回滚:

回滚之后,确实发现原来李四的数据也没有了,此时我们提交退出。但是如果我们直接使用rollback:

就会发现数据直接回滚到最开始了。

非正常演示:未commit,客户端崩溃,MySQL会自动崩溃。

插入数据之后没有commit,直接ctrl + D使MySQL崩溃(推荐使用CTRL + \),那么右侧事务中的表最开始还有,当左侧的MySQL崩溃之后就没有数据了,因为自动回滚,直接导致数据没有了。

非正常演示2: 证明commit了,客户端崩溃,MySQL数据不会在受影响,已经持久化

既然commit了,也就代表修改已经完成了,所以数据也已经持久化了了。

非正常演示3:单条SQL与事务的关系

顺序为终端A关闭autocommit之后,insert之后ctrl+\,终端B无法查询。

那么如果开启了autocommit,那么即便abort了也能查询到,因为已经持久化存储了。

那么以上,我们已经见识到了事务的原子性和持久性,对于事务的隔离性和一致性,我们放在后面详细介绍。


感谢阅读!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-06-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言:
  • 生活例子
  • 什么是事务
    • 为什么要有事务
    • 事务的版本支持
  • 事务操作
    • 事务的提交
    • 事务的操作
      • 事务的开始和回滚
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档