Mysql系列-事务

2021-11-01  本文已影响0人  程序员fly

前言

面试过程中,事务也是一种常见面试官常见爱问的点,目前大概内容如下

概念

  官方点的说法就是一组SQL语句组成的逻辑处理单元   通俗点理解就是Mysql经过一系列逻辑操作,这一系列操作必须全都成功,要不全部失败。事务有4个属性:原子性(A),一致性(C),隔离行(I),持久性(D),这四个属性我们称为ACID特性,ACID理论是对Mysql特性的抽象,简单理解就是如果你的操作满足ACID特性,你就实现了事务

并发事务

多个事务同时操作数据库,如果不才去任何机制,会出现,数据丢失,脏读,不可重复读等问题

隔离级别

数据库必须具有隔离并发运行各种事务的能力,使其之间不相互影响,避免各种并发问题,比如脏读,不可重复读和幻读等问题,Mysql定义了以下四种隔离级别(由低到高),这4个隔离级别可以逐个解决脏读,不可重复读,幻读这几个问题。

  1. 读未提交(Read uncommitted 简成rn):一个事务可以读取到另外一个事务未提交的修改。这个隔离级别最差,会产生脏读,幻读,不可重复读问题
  2. 读已提交(Read Commit):一个事务只能读取另外一个事务已经提交的修改,避免脏读,仍然会存在不可重复都和幻读的问题。Oracle默认隔离级别就是这个
  3. 可重复读(Repeated Read):相同事务多次读取相同的数据返回的结果都是相同的,避免的脏读和不可重复读的问题,但是没避免幻读。Mysql默认的隔离级别就是这个。Mysql通过多版本并发控制(MVCC),间隙锁的问题解决了幻读
  4. 串行话(Serializable):数据库最高的隔离级别,事务都会排着队一个个执行,能够解决上面几个问题,但是执行效率很差。

开启事务

实现原理

    先说结论,Mysql通过redo log和undo log保证事务的原子性,一致性和持久性,隔离性是同时锁方式来实现, 接下来一一介绍这几个名词。

redo log

·Redo log 称为重做日志,主要用来进行数据恢复使用,包含设计两部分内容,一部分是内存中日志缓冲(redo log buffer),该部分日志因为在内存中,重启之后会丢失,另外一部分是在磁盘中的日志文件(redo log file),这部分日志是持久的,接下来我们通过一个更新例子详细了解一下redo 日志的相关作用

数据更新流程
我们一般在开发过程中,一般下面类似这样的sql去更新数据库中的数据,今天我们来研究一下这个sql语句Mysql是如何执行的,博主在学习相关知识点的时候,发现CSDN上一篇博客[相关图](https://blog.csdn.net/javaanddonet/article/details/112596210?spm=1001.2014.3001.5501)简单明了(点击进入相关链接)以及Mysql45讲相关知识点,今天我们站在前辈的肩膀上学习一下相关知识点,如有侵权,请联系博主删除。
update user set name="程序员fly" where  id=8
20210113222656788 (1)

引用图片来源https://blog.csdn.net/javaanddonet/article/details/112596210#comments_18049709

如图所示,我们看到,客户端发送一起更新请求,需要Server层和存储引擎层

Server层
        我们常常使用的存储引擎,触发器,视图都在这一层上面实现,Server层只要有以下几个构成
存储引擎层

存储引擎主要设计数据的存储和提取的,当执行器传来具体的执行计划的时候,存储引擎是这样干的

通过上面一些列流程,只要Mysql中redo log持久化到磁盘中以后,当系统崩溃之后,就可以通过redo log来进行数据的恢复

undo log

        undo log主要有两个功能:实现事务回滚和多版本并发控制(MVCC),数据在进行修改的时候,不仅会记录redo log。还会记录相对于的undo log,如果过程中数据库异常等原因导致**事务失败会通过undo log进行事务回滚,实现原子性关键**,undo log记录的逻辑日志。

MVCC

undo log主要有两个功能:实现事务回滚和多版本并发控制(MVCC),在Mysql中数据是有版本这个概念的,同一条数据在系统中会存在多个版本,事务的隔离性实现就是通过对比数据版本来实现的,如果不可见,就通过undo log回滚到上一个版本,一直到比较对当前视图可见的值,我们来看一个例子(例子来源Mysql45讲),假设现在数据库中一个值为1,被顺序改成了2,3,4,在回滚日志中就会这样记录,如图
点赞视图

比如这个数据的当前值4,但是查询这个数据的时候,不同事务有不同的视图(read-view),视图A,B,C,D中对应的值分为为1,2,3,4。事务A在查询的数据的时候,会通过undo日志回滚到视图A所看到的的1,这样隔离我们想一下有什么好处 这样可以增加并发,我们查询的时候不用等到另外一个事务释放锁,使得不同事务的读-写,写-读操作能够并发执行,提升系统性能

总结

几个问题

**Q**:  redo  log buffer的日志是不是每次都生成之后都需要持久化到磁盘中?

**A**:不需要,如果执行期间Mysql事务发生异常重启,因为事务还没提交,日志丢失时候也没影响

**Q**:一个事务完成提交需要两次写入磁盘,一个redo log(prepare阶段),一个binlog,Mysql做了什么优化

**A**:  Mysql使用**组提交的机制**来进行优化,比如三个并发事务t1,t2,t3,对应的日志逻辑序列号LSN为10,20,30,我们简单理解为一段记录即可,t1提交的时候,直接提交LSN为30,t1返回的时候,将<30的都提交上去了,t2,t3完成之后直接返回,不用等待写磁盘。

**Q**:长事务会有什么问题

**A:**  长事务一直不释放,MVCC机制数据库上会有很长的回滚段。

巨人肩膀

https://www.cnblogs.com/f-ck-need-u/p/9010872.html

https://time.geekbang.org/column/intro/100020801

闲谈

公众号有自己总结的一系列文章,需要的小伙伴还请关注下个人公众号程序员fly点个赞,这将对我是很大的鼓励~

上一篇 下一篇

猜你喜欢

热点阅读