MySQL数据库事务完整详解
2026/6/25 14:13:28 网站建设 项目流程

事务是数据库保障数据一致性、处理并发操作的核心机制,拥有 ACID 四大特性。本文详细介绍事务基础语法、保存点机制,分析并发引发的脏读、不可重复读、幻读问题,讲解MySQL四大隔离级别

文章目录

    • 什么是事务
    • ACID特性
      • 原子性 Atomicity
      • 一致性 Consistency
      • 隔离性 Isolation
      • 持久性 Durability
    • 事务语法
    • 保存点
    • 事务的隔离性详解
      • 事物的隔离级别
        • 读未提交(Read Uncommitted)
        • 读已提交(Read Committed)
        • 可重复读(Repeatable Read)
        • 串行化(Serializable)
      • 设置事务隔离级别

什么是事务

事务是一个不可分割的工作单位(原子的),是用户定义的数据库操作序列,也就是将多个操作打包成一个整体,这些操作要么都做,要么都不做,不会出现其他情况

经典场景:转账、抢票、选课等等

针对转账这个场景来说,A给B转200元,这一过程,A的余额要减200元,B的余额要加200元,这两个操作同时进行,并且不受其他操作的影响。这时就需要使用事务,将这两个操作当成一个整体,要么转账成功,要么转账失败,金额和转账前保持一致;不会出现只扣A余额、不增加B余额,或是只增加B余额、不扣除A余额等这类数据不一致的异常情况。

事务是恢复和并发控制的基本单位。并发是指多个事件在同一时间段内执行,宏观上看是多个事件同时执行

对数据库进行操作时,结果超出预期的原因就是因为并发

ACID特性

事物的ACID分别指原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)

原子性 Atomicity

原子性是指一个事务中的所有操作当成一个不可分割的整体,使这些操作要么全部执行成功,要么全部执行失败,并将执行失败的操作还原回初始状态。

这里需要注意的是对于更新操作来说,在执行操作前会先打印初始数据的日志,然后再执行操作。之所以事务执行失败时数据看起来没发生任何改动、操作看起来没执行,是因为会将已经执行的操作根据日志将其还原回初始状态,而这个还原数据的过程叫回滚(rollback)

当事务执行成功或者执行完回滚操作后,这就标志着这个事务的完成和结束

而在事务完成后,这个事务所记录的日志就失效了,系统会自动清理该日志

而我们之前对表进行的增删改查操作,也是依托了事务机制,MySQL在执行SQL语句前会默认开启事务,执行成功后会默认提交事务,如果执行失败会进行回滚,并打印报错信息

一致性 Consistency

一致性是指事务的执行结果必须是从一个一致性状态变为另一个一致性状态

隔离性 Isolation

隔离性是指事务内部的操作与其他事务是隔离的、互不干涉的,不会因为

持久性 Durability

持久性也叫永久性,在事务完成后,其对数据的修改是永久性的,并写入对应的表中,不会因为其他情况而造成数据的丢失

事务语法

先简单了解一下事务语法,后续会详细说明

-- 开启事务starttransaction;begin;-- 提交事务commit;-- 回滚rollback;

其中,commit 和rollback都表示这个事务的结束标志

例如:

begin;#1insertintostudentvalues(1,'张三','男');insertintostudentvalues(2,'李四','女');#2rollback;#3insertintostudentvalues(3,'王五','男');#4insertintostudentvalues(4,'赵六','女');commit;#5

执行1-2之间的语句,查询student表:

执行3,对该事务中已执行的所有SQL语句进行回滚,查询得

此时,这个事务结束

再来,重新开启一个事务,执行1-2、4-5,查询得:

执行了commit表示这个事务结束,此时执行回滚操作无效,表没有发生任何改变:

保存点

事务的局部回滚,保存点可以指定部分SQL语句的回滚,将保存点之后、当前执行位置之前的SQL语句进行回滚

savepoint保存点名称;#创建保存点rollbackto保存点名称;#从指定保存点开始回滚

其中,执行完’rollback to 保存点名称;’ 后该事务不会结束,只有在’rollback’或者’commit’执行完毕后才表示整个事务完成,而此时该事务的所有保存点失效

例如:

begin;#1insertintostudentvalues(1,'张三','男');insertintostudentvalues(2,'李四','女');savepointa;insertintostudentvalues(3,'王五','男');savepointb;insertintostudentvalues(4,'赵六','女');#2rollbacktoa;#3rollbacktob;#4rollback;#5

执行1-2,查询得:

执行3,此时会将 a保存点 至 2之间的SQL语句进行回滚,查询得:

此时事务还没结束,执行5,会将该事务已执行的所有SQL语句进行回滚:

此时,该事务结束

事务的隔离性详解

在前面,我们提到,事务的隔离性是指事务内部的操作与其他事务相隔离,互不干涉

事务是恢复和并发控制的基本单位。并发是指多个事件在同一时间段内执行,宏观上看是多个事件同时执行,所以并发性越好、执行效率越高

并发操作会出现脏读、不可重复读、幻读问题,而事务的隔离级别的设置可以解决对应的问题

事物的隔离级别

在MySQL的InnoDB引擎中,事务的隔离级别可分为读未提交(低)、读已提交、可重复读、串行化(高)。MySQL的InnoDB引擎默认隔离级别是可重复读

隔离级别越高,数据的完整性越高,并发性越差,效率越低;隔离级别越低,数据的完整性越低,并发性越好,效率越高

完整性包括数据的正确性和数据的相容性

读未提交(Read Uncommitted)

字面意思理解就是允许读取未提交的数据,这一隔离级别是出现脏读的主要原因

我们先谈谈什么是脏读,脏读就是读取到的数据是无效的、不正确的。常见的是B事务读取了A事务中修改了但未提交的数据,然后A事务将该数据进行回滚了,此时B事务中拿到的数据就是脏数据,这个读取过程就是脏读

读未提交这一隔离级别没有对这两个事务的执行顺序进行干预

读已提交(Read Committed)

读已提交这一隔离级别对事务的执行顺序进行了一定干预。它规定,B事务只能读取A事务执行完成后的数据。

所以,读已提交解决了脏读问题

但是,又出现新的问题了:

事务C中先后读取D的值,发现前后两次读取的值不一致,这就是不可重复读问题

可重复读(Repeatable Read)

可重复读隔离级别可以解决不可重复读问题,它涉及到了快照机制,就是事务在执行select操作时,搞了份快照,可以理解为复制了一份,后续读取对应数据时,不会读取最新修改的,而是读取快照里面保存的数据

这个隔离级别已经能处理一些幻读问题,但在特殊情况下,仍然处理不了

串行化(Serializable)

可重复读这一隔离级别解决了同个事务中,先后读取的值不一致的情况;那么,串行化解决的是同个事务中先后读取的数据集不同的情况,可以从根本上解决的是幻读问题

幻读:

串行化就是使事务进行串行操作,就是使多个事务依次按照顺序执行,只有在执行完当前事务后,才能开启下个事务,且同一时间只能执行一个事务

设置事务隔离级别

全局级别语法,数据库服务器重启后失效:

-- 语法1setglobaltransactionisolationlevel隔离级别;-- 语法2set@@global.tx_isolation='隔离级别';

事务隔离级别永久生效要修改.ini文件里面的配置,文件路径通常在‘C:\ProgramData\MySQL\MySQL Server 8.0\my.ini’

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询