

**前引:**数据是业务的核心,而事务是数据可靠性的 "守护神"。在 MySQL 中,事务看似简单的 "提交 / 回滚" 操作,背后藏着 ACID 特性的严格约束、隔离级别的底层实现,以及并发场景下的锁竞争逻辑。很多开发者因为一知半解,导致系统出现脏读、幻读、数据丢失等严重问题。今天,我们就来层层拆解 MySQL 事务,让你从 "会用" 到 "精通",真正守住数据一致性的底线!
目录
【一】事务介绍
事务是一组DML相关的语句(操作指令)集合,这些指令要么成功/不成功,满足如下性质:
- 原子性(Atomicity):操作不可分割,要么全成要么全败
- 一致性(Consistency):事务前后数据库完整性不被破坏
- 隔离性(Isolation):并发事务互不干扰,避免脏读、幻读等问题
- 持久性(Durability):事务提交后,数据修改永久有效
【二】为什么要有事务
事务是为了服务应用层而存在,数据库是存储数据的地方,那么应用层对数据进行的操作就必须保障数据的一致性,这些关心事情(比如我这次的修改数据会不会不成功、等下有没有可能就没有了)应该人性化的交给MySQL自己实现,因此它是一个服务机制(为应用层服务)
【三】事务的版本支持
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务, MyISAM 不支持
cpp
mysql> show engines; -- 表格显示
mysql> show engines \G -- 行显示


【四】事务提交的两种方式
事务的提交方式常见的有两种: 自动提交 和 手动提交
查看事务提交方式:
cpp
show variables like 'autocommit';

用 SET 来改变 MySQL 的自动提交模式:
cpp
SET AUTOCOMMIT=0; #SET AUTOCOMMIT=0 禁止自动提交
SET AUTOCOMMIT=1; #SET AUTOCOMMIT=1 开启自动提交

【五】事务的几种操作
(1)开始一个事务
cpp
begin;
(2)创建一个保存点
cpp
savepoint 自命名;

(3)回滚到指定保存点
cpp
rollback to 保存点名字;

(4)正常结束一个事务
注意:正常结束一个事务后,不支持回滚
cpp
commit;

(5)异常结束一个事务
注意:异常结束自动回滚,由于原子性,自动回到事务未提交时的数据状态
cpp
Aborted;
【六】事务隔离级别
(1)**读未提交:**在该隔离级别,所有的事务都可以看到其他事务没有提交的 执行结果。(实际生产中不可能使用这种隔离级别的),但是相当于没有任何隔离性,也会有很多 并发问题,如脏读,幻读,不可重复读等!
理解:假设多个客户端并发访问操作同一个数据,单个客户端的任何操作不管提交与否,其它人都看的到
总结:不管对方提交与否,都看得到数据的修改
(2)**读提交:**该隔离级别是大多数数据库的默认的隔离级别(不是 MySQL 默 认的)。它满足了隔离的简单定义:一个事务只能看到其他的已经提交的事务所做的改变。这种隔离级别会引起不可重复读,即一个事务执行时,如果多次 select, 可能得到不同的结果!
理解:假设A在操作一个事务,B也在操作一个事务
A和B都在修改表1,A在执行commit之前,B是看不到A做出的修改的
一但A做出了提交,B就可以看到A的修改
总结:只要对方提交了,哪怕是多个事务,数据修改就会被其它人看到
(3)**可重复读:**这是 MySQL 默认的隔离级别,它确保同一个事务,在执行中,多次读取操作数据时,会看到同样的数据行。但是会有幻读问题!
理解:假设A在操作一个事务,B也在操作一个事务
A和B如果操作同一个表,此时A完成了提交,B是看不到修改的,B看到的是B进入该事务开始时的数据,如果A退出事务了,那么B的数据就会更新到最新的
总结:只有单方提交且退出事务,对方才看得到更改
什么是幻读?假设A修改了张三的年龄,然后提交退出事务,B此时可能在筛选年龄时出现两个张三,因为A提交且退出事务了,B就会更新数据
(4)**串行化:**这是事务的最高隔离级别,它通过强制事务排序,使之不可能相互冲突, 从而解决了幻读的问题。它在每个读的数据行上面加上共享锁!
总结:一把锁,你访问数据是没有问题的,当你修改数据时,只有在你前一个事务修改完了你才可以执行修改的操作,即串行化,唯一就是效率低
【七】事务相关结论
(1)持久化保障:只要开始一个事务,输入begin或者start transaction,事务便必须要通过 commit提交,才会持久化,与是否设置自动提交无关
(2)事务可以手动回滚,同时,当操作异常,MySQL会自动回滚
以上可以看出事务的原子性和持久性:要么成功要么不成功,数据一经提交,就是持久化
而原子性保障了数据的一致性,
【八】修改事务隔离级别
- 读未提交 :
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; - 读提交 :
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; - 可重复读 (默认):
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; - 串行化 :
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
【九】客户端会话与事务关系
客户端会话并非是一个事务,一个客户端中可以允许多个事务,事务之前相互独立
【十】进阶:数据并发的场景
数据并发场景有以下三种:
读-读 :不存在任何问题,也不需要并发控制
读-写 :有线程安全问题,可能会造成事务隔离性问题,可能遇到脏读,幻读,不可重复读
写-写 :有线程安全问题,可能会存在更新丢失问题,比如第一类更新丢失,第二类更新丢失
什么是读and读?读写、写写就自然明白了
多个用户访问同一块数据不存在安全问题,因为只访问不修改
读-写
用来解决读-写的方案:多版本并发控制( MVCC )(无锁并发控制)
解决问题:读写互不阻塞
如何解决?超易懂版本
MVCC依靠三个工具:
(1)数据的额外三个标签:最近修改的事务ID、回滚指针、隐式主键
(2)快照仓库(针对写操作):当修改数据时会保存一份原始数据在 undo 日志里面,回滚指针 指向该原始数据
(3)读视图(针对读操作):形成读视图,给当前事务划分可见范围,看不到未提交的或者在你 后面提交的数据版本
运行过程:当A去修改数据时,会加行锁(保证修改的原子性),先将原始数据放在 undo 仓库,如果有读端访问,访问的是 undo 仓库里面的,看不到A的修改,因为有视图范围,读写可以同时进行,视图通过划分范围可以自行屏蔽脏读------四种隔离性无非是对这三个工具"度"的把控
