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

相关推荐
emo了小猫9 分钟前
Mybatis #{} 和 ${}区别,使用场景,LIKE模糊查询避免SQL注入
数据库·sql·mysql·mybatis
潘yi.5 小时前
NoSQL之Redis配置与优化
数据库·redis·nosql
zdkdchao5 小时前
hbase资源和数据权限控制
大数据·数据库·hbase
伤不起bb5 小时前
NoSQL 之 Redis 配置与优化
linux·运维·数据库·redis·nosql
leo__5205 小时前
PostgreSQL配置文件修改及启用方法
数据库·postgresql
南風_入弦7 小时前
优化09-表连接
数据库·oracle
Snk0xHeart8 小时前
极客大挑战 2019 EasySQL 1(万能账号密码,SQL注入,HackBar)
数据库·sql·网络安全
····懂···8 小时前
数据库OCP专业认证培训
数据库·oracle·ocp
学习中的码虫9 小时前
数据库-MySQL
数据库
天天摸鱼的java工程师9 小时前
高考放榜夜,系统别崩!聊聊查分系统怎么设计,三张表足以?
java·后端·mysql