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

相关推荐
小陶来咯40 分钟前
【高级IO】多路转接之单线程Reactor
服务器·网络·数据库·c++
wei_shuo42 分钟前
OB Cloud 云数据库V4.3:SQL +AI全新体验
数据库·人工智能·sql
潇湘秦2 小时前
Oracle非归档模式遇到文件损坏怎么办?
数据库·oracle
极小狐3 小时前
如何使用极狐GitLab 软件包仓库功能托管 maven?
java·运维·数据库·安全·c#·gitlab·maven
野犬寒鸦4 小时前
MySQL索引使用规则详解:从设计到优化的完整指南
java·数据库·后端·sql·mysql
时序数据说5 小时前
IoTDB磁盘I/O性能监控与优化指南
大数据·网络·数据库·时序数据库·iotdb
火云牌神5 小时前
在windows系统中安装图数据库NEO4J
数据库·windows·neo4j
A尘埃7 小时前
K8S有状态服务部署(MySQL、Redis、ES、RabbitMQ、Nacos、ZipKin、Sentinel)
redis·mysql·kubernetes
吻等离子7 小时前
解决 MySQL 数据库无法远程连接的问题
数据库·mysql·adb
八股文领域大手子7 小时前
密码学基石:哈希、对称/非对称加密与HTTPS实践详解
数据库