【MySQL】事务

事务

在讨论事务之前,我们要知道只有在InnoDB存储引擎下才能执行事务。

首先,让我们思考一个问题,在我们写下SQL语句,按下回车键之后,MySQL究竟是怎么来完成我们想要执行的语句呢?

在这里插入图片描述

通过这张图,我们可以看到最主要的步骤就是缓存机制,其中MySQL支持一种Buffer pool机制,主要的处理模式是MySQL是一种文件类型数据库即MySQL将数据都存储在文件中,对数据的任何操作都意味着要对文件操作,那必须要进行文件IO(磁盘IO),但是磁盘IO非常耗时,如果将文件中的一部分数据拿到缓存中存储,再去操作数据的时候就可以只操作缓存。

InnoDB作为MySQL的存储引擎,数据是存放在磁盘中的,但如果每次读写数据都需要磁盘IO,效率会很低。为此,InnoDB提供了缓存(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射,作为访问数据库的缓冲:当从数据库读取数据时,会首先从Buffer Pool中读取,如果Buffer Pool中没有,则从磁盘读取后放入Buffer Pool;当向数据库写入数据时,会首先写入Buffer Pool,Buffer Pool中修改的数据会定期刷新到磁盘中(这一过程称为刷脏)。Buffer Pool的使用大大提高了读写数据的效率,但是也带了新的问题:如果MySQL宕机,而此时Buffer Pool中修改的数据还没有刷新到磁盘,就会导致数据的丢失,事务的持久性无法保证,所以我们需要使用mysql中的日志来保证数据持久性的。

我们接着分析这张图,可以看到除了缓存外,还有很多其他比较重要的操作,比如:

  • 解释器:是通过关键字将SQL语句进行解析,并生成对应的解析树。MySQL解析器将使用MySQL语法规则验证和解析查询。
  • 解析树:判断SQL语法是否正确。
  • 预处理器:则是根据一些MySQL规则进行进一步检查解析树是否合法,例如检查数据表和数据列是否存在,还会解析名字和别名,看看它们是否有歧义。
  • 查询优化器:查询优化器会将解析树转化成执行计划。一条查询可以有多种执行方法,最后都是返回相同结果。优化器的作用就是找到这其中最好的执行计划。

在这里我们也要注意,不同的存储引擎数据存储的方式是不同,操作数据时操作数据的方式也是不同。

那么我们分析一下,如果我们在使用MySQL时,SQL语句被执行到了缓存中,但是并没有进行刷脏操作,此时因为停电导致MySQL异常中断,导致数据丢失应该怎么办?

这里我们是可以不用担心的,因为MySQL在底层已经考虑到了这种问题,在这时MySQL是会保证数据的持久性,其中最主要的机制就是数据库管理机制(DBMS),它保证了对数据库中的数据的修改是永久性的,即使数据库因为故障出错,也应该能够恢复数据!

那么具体又是怎么实现的呢?这里就引出了MySQL的持久性实现原理:即redo log 日志。

当数据修改时,除了修改Buffer Pool中的数据,还会在redo log记录这次操作;当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。

接下来,我们分析以下生活中的实例,我们都知道MySQL的SQL语句在按下回车键之后就会执行,那么如果我们在对银行卡里面的钱数进行操作时,所执行的钱数与银行卡里的钱数不匹配,造成转账过程出错,此时对于数据库来说,应该怎么处理呢?

这里就用到了事务。那么事务又是什么呢?

事务的定义

一个事务是由一条或者多条对数据库操作的SQL语句所组成的一个不可分割的单元,只有当事务中的所有操作都正常执行完了,整个事务才会被提交给数据库;如果有部分事务处理失败,那么事务就要回退到最初的状态,因此,事务要么全部执行成功,要么全部失败。

一旦开启事务就不是按下回车键就会造成持久性修改的操作了,即MySQL将不会在第一时间自动提交SQL语句,而是要进行二次判断,如果发现SQL语句中有执行错误的SQL 语句那么可以直接调用 rollback 退回至初始状态,如果没有发现任何执行错误的SQL语句才会执行 commit 进行手动提交,这个时候才会对数据造成持久性的影响。

而此时,事务的操作利用了其本身的特性之一:原子性,它的实现原理是undo log 日志,undo log中会记录一条和你执行的sql语句意义相反的sql语句,当你rollback时就执行undo log中的sql语句。例如:

  • 当执行insert语句时,undo log日志中会记录对应的delete语句。
  • 当执行delete,会记录所对应的insert语句。
  • 执行update 语句时,会记录相反的update语句。

当我们执行rollback时,可以读取undo log 日志然后回滚数据。当我们执行commit之后就会对undo log 日志进行数据清空,此时如果在想rollback就不行了。

实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。InnoDB实现回滚,靠的是undo log:当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。undo log属于逻辑日志,它记录的是sql执行相关的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值