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#事务有哪些特性

相关推荐
cg50171 小时前
MySQL数据库复杂的增删改查操作
数据库·mysql
虾球xz2 小时前
游戏引擎学习第147天
数据库·学习·游戏引擎
向上的车轮3 小时前
什么是时序数据库?有哪些时序数据库?常见的运用场景有哪些?
数据库·时序数据库
岱宗夫up4 小时前
【Python】Django 中的算法应用与实现
数据库·python·opencv·django·sqlite
比花花解语5 小时前
使用数据库和缓存的时候,是如何解决数据不一致的问题的?
数据库·缓存·数据一致性
YGGP5 小时前
Redis篇:基础知识总结与基于长期主义的内容更新
数据库·redis·缓存
KINICH ahau5 小时前
数据库1-2章
数据库·oracle
我想吃烤肉肉6 小时前
leetcode-sql数据库面试题冲刺(高频SQL五十题)
数据库·sql·leetcode
夏炎正好眠7 小时前
mysql练习
数据库·mysql
NineData7 小时前
NineData 社区版正式上线,支持一键本地化部署!
数据库·程序员