-–
title: Mysql 事务隔离
date: 2020
categories: mysql
-–
关于 mysql 的事务隔离级别,在很多地方都有看过相关文档,对于面试来说基本也是必考题,本来也不想再写一篇文档来赘述这个事,不过最近在读完了掘金小册 《从根儿上理解 MySQL》之后有了新的感悟,遂希望自己可以总结一下
无论设计什么系统也好,只要你不是单进程单线程,那么并发的问题总是 绕不过的, mysql 也不例外,如两个事务并发执行会发生什么? Mysql 是如何巧妙的解决这些问题的呢? 所以,也就有了本章的主题,事务的隔离性。
事务并发
在解释问题之前,我希望能阐述清楚事务并发执行会产生什么后果。
一、脏写
当两个事务同时尝试更新一条数记录的时候,必定会存在一前一后的执行,如下图所示,事务 T1 在提交之后,事务 T2 进行回滚了,也就是说 T1 费老大劲最后啥也没改变,关键是 T1 肯定觉得莫名奇妙,到底谁动了我的奶酪?
事务执行导致脏写
脏写就是未提交的事务改动了另一个未提交事务的记录
二、脏读
当两个事务一前一后更新和读取数据的时候,会造成后面读取数据的不准确。
事务执行导致脏读
当事务 T1 先更新数据,T2 读到的数据是 T1 更新后的数据,但之后,T1 竟然回滚了,那么 T2 原本读到的数据实际上就不准确了。(T1 做了个假动作虚晃一枪)
三、不可重复读
当一个事务重复读取同一条记录,但前后的数据不一致时(被其它进行中的事务改动了),结果就产生了不可重复读。(PS:在平时写业务的过程中,有些场景其实是希望能读到最新的数据的)
不可重复读
在事务 T1 执行到第四行select * from accounts where id = 1的时候,得到的值是 T2 更新后的值,就称之为不可重复读。而可重复读的情况是,在一个事务内,第一次读到的结果和第二次,第三次,第四次…第 N 次 读到的结果应该是一致的,只要他们都属于同一个事务而且未结束。
四、幻读
幻读的场景其实和不可重复读的情况类似,两次查询的结果条数不一致便称之为幻读。区分与不可重复读的区别就是幻读是范围查询,而不可重复读是仅查询一条记录
幻读
在第二次范围查询 accounts 表的时候,另一个事务插入了一条符合条件的数据,导致第一次查询的结果(返回 1 )和第二次返回的查询结果(返回 2)产生了不一致,就称之为幻读。而不产生幻读的情况是什么呢?在一个事务内,第一次查询的结果和第二次,第三次,… 第 N 次 的结果一致,只要他们都属于同一个事务而且未结束。
按照几种隔离级别,我们可以排个序:
脏写 > 脏读 > 不可重复读 > 幻读
脏写是无论如何都不能发生的,因为会导致数据错乱的问题,所以无论哪种隔离级别都解决了脏写的问题。
而 MySQL 的默认隔离级别是 可重复度,REPEATABLE READ
多版本并发控制 Multiversion Concurrency Control(MVCC)
InnoDb 行格式
原理
共享锁,排他锁,傻傻分不清楚?
死锁
饿死锁
Q&A
- 死锁的时候,回滚的是哪个事务?两个都回滚?还是只回滚一个?如果回滚一个的话,那么回滚哪个呢?
- 为什么排他锁一定要在事务完成后才能释放?如果在操作完某一项以后进行释放会产生什么问题? 383
install_url to use ShareThis. Please set it in _config.yml.