mysql事务超全~

大家好,我是程序媛雪儿,今儿咱聊聊mysql事务。

咱们先看一下什么是事务。

事务是什么

事务是一组操作的集合,是一个不可分割的工作单位,事务会把所有的操作作为一个整体向系统提交或者撤销操作,也就是说,这些操作要么同时成功,要么同时失败。

特性(ACID)

原子性(Atomicity):事务是不可分割的最小操作单元(要么都成功,要么都失败)

一致性(Consistency):事务完成时,必须使所有数据保持一致

隔离性(Isolation):数据库提供隔离机制,保证事务不受外部并发操作影响,在一个独立环境下运行

持久性(Durability):事务一旦提交或回滚,对数据库的改变是永久的,也就是说会保存到磁盘上

并发事务问题

有哪些

脏读

一个事务读到另外一个事务还没有提交的数据

事务A更新完数据还没提交,事务B此时读到了A还没提交的数据

不可重复读

一个事务先后读取同一条记录,但两次读取的数据不同

事务A第一次读到的是旧数据,第二次读这个数据前,这个数据已经被事务B改了,所以事务A第二次读到的数据和第一次读到的同一条数据不一样

幻读

一个事务按照条件查询数据的时候,没有对应的数据,但是在插入数据的时候,又发现这行数据已经存在了,好像出现了幻影

当事务A查数据库,发现id为1的数据没有,此时事务B把id为1的数据已经插入到数据库中,事务A再插入id为1的数据报错,再查id为1的数据,还是没有(因为解决了不可重复读,保证了两次数据一致)

解决方案

|----------|----|-------|----|
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
| 未提交读 | √ | √ | √ |
| 读已提交 | × | √ | √ |
| 可重复读(默认) | × | × | √ |
| 串行化 | × | × | × |

注:事务隔离级别越往下安全性越高,但是性能越差

事务的隔离级别是如何实现的?

本质还是老两套

锁:排他锁(一个事务获得了某一行,其他事务就不能再获取该行的锁了)

mvcc:多版本并发控制

什么是MVCC?

维护一个数据的多个版本,使得读写操作没有冲突

来看下面这个例子

MVCC的实现,主要依赖数据库记录中的隐式字段、undo log日志、readView

隐藏字段

|-------------|-------------------------|
| 隐藏字段 | 含义 |
| DB_TRX_ID | 最近修改事务ID,最后修改这条记录的事务ID |
| DB_ROLL_PTR | 回滚指针,指向是这条记录的上个版本 |
| DB_ROW_ID | 隐藏主键,表结构中如果没有主键就会生成这个字段 |

undo log日志中的版本链

事务对同一条记录修改,就会生成记录版本链,链表头部是最新的数据记录,尾部是最老的数据记录

readview

readview是快照读SQL执行时提取数据的依据。

这里聊到了一个概念,快照读,我们先搞明白什么是当前读和快照读

当前读:读取的是记录的最新版本,并且保证其他并发事务不能修改当前的记录(加锁)

快照读:读取的是记录数据的可见版本,可能是历史数据(不加锁、非阻塞)

|----------------|-----------------------------|
| 字段 | 含义 |
| m_ids | 当前活跃的事务ID集合(活跃的事务指的是未提交的事务) |
| min_trx_id | 最小活跃事务ID |
| max_trx_id | 最大事务ID+1 |
| creator_trx_id | 当前事务ID,readview创建的事务ID |

访问规则

trx_id代表的当前事务,在undo log日志当中,会依次遍历DB_TRX_ID,去找第一个符合的版本数据返回给用户

不同的隔离级别,生成的readview不同

read committed (读已提交):每次执行快照读时生成readview

事务5中查询id为30的记录,根据访问规则+生成的readview,第一次查询读到的是事务2,第二次查询读到的是事务3

repeatable read(可重复读):仅在事务第一次执行快照读时生成readview,后续复用该readview,保证在一个事务中读到的版本是一样的

事务5中查询id为30的记录,根据访问规则+生成的readview,第一次读到的是事务2,第二次查询读到的还是事务2,因为复用的第一个ReadView。

欢迎大家关注我的微信公众号,程序媛雪儿,雪儿会在上面发布编程的知识碎片,也有雪儿博客地址,上面有详细系统的笔记,雪儿是全栈,但是公众号目前主要还是发后端的技术,以后可能也会涉及到一些前端的知识,我们下期见,拜拜~

相关推荐
kejijianwen2 小时前
JdbcTemplate常用方法一览AG网页参数绑定与数据寻址实操
服务器·数据库·oracle
编程零零七2 小时前
Python数据分析工具(三):pymssql的用法
开发语言·前端·数据库·python·oracle·数据分析·pymssql
高兴就好(石5 小时前
DB-GPT部署和试用
数据库·gpt
这孩子叫逆6 小时前
6. 什么是MySQL的事务?如何在Java中使用Connection接口管理事务?
数据库·mysql
Karoku0666 小时前
【网站架构部署与优化】web服务与http协议
linux·运维·服务器·数据库·http·架构
码农郁郁久居人下6 小时前
Redis的配置与优化
数据库·redis·缓存
MuseLss7 小时前
Mycat搭建分库分表
数据库·mycat
Hsu_kk8 小时前
Redis 主从复制配置教程
数据库·redis·缓存
DieSnowK8 小时前
[Redis][环境配置]详细讲解
数据库·redis·分布式·缓存·环境配置·新手向·详细讲解
程序猿小D8 小时前
第二百三十五节 JPA教程 - JPA Lob列示例
java·数据库·windows·oracle·jdk·jpa