MySQL 事务

MySQL事务的特性

  • 原子性: 要么全部成功,要么全部失败(undo log)
  • 一致性: 事务会按照管理员制定的规则运行,保持数据的一致
  • 隔离性: 多事务并行的情况下,事务之间是不会相互影响的(mvcc)
  • 持久性: 事务一旦提交,便会持久化到磁盘,不会丢失数据.(binlog)
问题1 : 一致性是什么?在哪里有体现?

网路上的解释:

A有2000元,啊B有500元,两个人总计2500元。然后A给B转账1000元,A的余额减1000元,B的余额加1000元,这时 A的余额1000元,B的余额1500元,总计还是2500元,事物前后的数据是一致的。不会出现 A 的钱扣了,B 的钱没有增加 的情况.

这种看起来很模糊,感觉和原子性类似,要么全部成功要么全部失败,一致性就像是强行塞进去的一种性质.

而且这样描述 MySQL 事务的一致性是可以被人为打破的

因为 MySQL 的语句是程序员定义的,他想怎么写就怎么写,如果程序员可以写一个有问题的程序,MySQL 事务的一致性不就被打破了吗?

比如:程序员可以写给 A 扣 1000 元,只给 B 加五百元.(MySQL 的语句是可以自定义的),那么不就有 500 元凭空消失了吗,MySQL 开始前总金额是 2500,事务执行后就只剩 2000 元了.是不是意味着MySQL 的一致性被打破了.

但事实上 MySQL 的一致性与其他几种性质一样,无论 MySQL 的语句如何变化,都能保持他的四种特性

所以一致性到底是什么?
  • 事务会按照管理员制定的规则运行,保持数据的一致

比如: 制定的规则是 扣除金额=增加金额,那么事务结束总金额一定是相同的,数据是一致的

如果制定的规则是 扣除金额是增加金额的两倍,那么总金额一定会丢失扣除金额的一半,因为MySQL 是按照管理员制定的规则进行运行保持数据的一致.而不是根据他的值,最后值的变化一定是满足管理员的规则的.这便是数据的一致性

感觉没什么用,因为所有的程序都是根据程序员制定的规则进行运行的.这本来就是一个常态.

MySQL 的事务是如何工作的?

数据的隐藏列与事务的Read View

隐藏列
  • 数据除了我们定义的一些列之外还有一些隐藏的列

trx_id 是事务版本的id, undo log指向之前数据的状态

事务的Read View (mvcc)

每一个事务在创建的时候都会有一个Read View

包含:

creator_trx_id: 创建的事务 id

m_ids.:目前活跃的事务 id

min_trx_id: 最小的活跃事务 id

max_trx_id:下一个创建的事务的 id(最大活跃的加 1)

事务每次更改数据都会记录更改的事务与更改之前的状态(undo log)

什么时候数据是可见的?
  1. 小于最小事务 id,说明事务开始前就已经提交了,所以是可见的
  2. 小于最大事务 id+1 并且不在活跃事务 id列表中的,说明已经提交了

MySQL 事务的隔离形式与读取数据不一致的问题

  • MySQL的事务是并发(也可以串行)运行,并且是相互隔离的,那就会有一些数据读取不一致的问题
读未提交

读取最新版本的数据

脏读
  • 事务 b 修改一条数据(未提交),事务 a 读取这条数据,这时 b 事务回滚,事务 a 再一次读取这个数据
  • 这时事务 a 中两次读取的数据的结果是不一样的,这就是脏读
读提交

每次都会刷新事务的 Read View ,确保可见所有的已提交记录,获取已提交的最新的数据

不可重复读
  • 事务 a 读取一条数据,之后事务 b 修改这条数据(提交),事务 a 再一次读取数据,
  • 这时事务 a 中两次读取的数据的结果是不一样的,这就是不可重复读
可重复读

事务的Read View 不会改变,可见的数据不会改变,每次可以获取到的数据都是事务开始之前的状态

幻读
  • 事务 a 读取m 到 n 区间的数据, 之后事务 b 添加一条 m 到 n 区间的数据 ,事务 a 再一次读取m 到 n 区间的数据数据,
  • 这时事务 a 中两次读取的数据的结果(条数)是不一样的,这就是幻读.
串行化

单线程依次的执行,一般很少使用,性能太低

MySQL 默认使用的是可重读

可重复读可以完全避免幻读的问题吗?

不可以,有两种情况可重复读还是会出现幻读

  1. 事务 A(读区间,更改区间,再读区间);事务 B(在事务 A期间,更改前插入或者删除了某条数据),会出现幻读的情况
  2. 事务A先用读快照(普通 select), 事务 B 插入一条数据,再使用读当前(select...for update)就会出现幻读

可以理解update 是要使用最新的数据进行 update,就会去发现最新的数据,可见范围就变了,就出现了幻读.

参考
https://blog.csdn.net/yzf279533105/article/details/129370396

https://www.xiaolincoding.com/mysql/transaction/mvcc.html#事务有哪些特性

相关推荐
xxwl5853 分钟前
数据库后端接口测试报告
spring boot·mysql·tomcat
xqqxqxxq31 分钟前
MySQL 数据类型笔记
数据库·笔记·mysql
Logintern091 小时前
理解MySQL数据库的“事务与锁”
数据库·mysql
朱容zr3331331 小时前
为什么推荐使用自增主键?使用UUID作为主键的优缺点是什么?
java·运维·数据库·后端·mysql·面试·性能优化
麻瓜code1 小时前
【Redis 】数据类型、持久化与过期删除
数据库·redis·缓存
空杆推不起1 小时前
穿透 Flink CDC 表层用法:数据库日志捕获机制、Flink Source 运行时、端到端一致性底层原理详解
大数据·数据库·flink
朱容zr3331332 小时前
请解释“回表”的概念。
java·前端·数据库
大黄说说2 小时前
EF Core 避坑指南:查询慢、循环查询、并发更新问题如何解决
java·服务器·数据库
城管不管2 小时前
重生——第五次面试2026.8.1一面
java·数据库·后端·ai·面试·职场和发展·agent
ocean'2 小时前
防火墙策略路由
linux·服务器·数据库