事务机制主要是利用undo、redo日志?

为什么数据库需要事务机制

答: 如果数据的写入直接操作数据文件是非常危险的事情

事务机制主要是利用undo、redo日志?
如上图,比如说现在写了一个update语句,要给员工涨工资,执行的过程中系统突然重启了,这时候我们就搞不清楚那些数据修改了,那些数据还没有修改,因为没有原始数据做对比,所以数据发生混乱后,就特别不好维护,所以说用sql语句直接操作后端文件遇到突然事件的后果是非常严重的。

利用日志来实现间接写入

如果想让sql语句不直接修改数据文件,这时候就要引入事务机制了,MySQL总共有5种日志,其中只有redo日志和undo日志与事务有关。

事务机制主要是利用undo、redo日志?

  1. 日志文件相当于数据的一个副本,sql语句操作什么样的数据,这些数据会被复制到undo日志里
  2. 增删改查结果会记录在redo日志里
  3. 假如增删改查的操作没有问题,那么把数据同步到数据里就行
    3.1 即便同步过程中,遇到停电死机之类问题,由于有redo日志文件存在,所以系统恢复后,继续让redo文件同步

事务就是靠redo和undo日志建立起来的一种操作数据的机制,理解了undo、redo日志的作用,事务机制就搞明白了一半。

事务机制

事务机制在数据读写方面的重要性不言而喻,这是站在数据库本身而言,再站在使用者的角度看下事务机制对 业务处理有多重要

  • 事务是一个或多个sql语句组成的整体,要么全部执行成功,要么全部执行失败

在教科书上说,在事务机制下,所有的sql语句当做一个整体,要么这些sql语句全都执行成功,要么全都失败,绝对不会出现有的sql语句执行成功,而另外一些sql语句执行失败,在实际的业务中事务 这个特性是非常重要的。

比如说某个商业系统为新注册的用户发放代金券,这个业务里面会用到两条sql语句,我们能接收的正确结果是要么用户注册成功和领取了代金券,要么没有注册成功也没有领取代金券,其它的结果我们是不能接受的——用户没有注册成功领到了代金券或者注册成功但是没有领取到代金券。
恰好事务能够满足业务流程里每个步骤都必须成功,或者某个步骤失败,撤销流程里的全部操作。

以上的描述,我们只是知道了事务机制的结果,但是undo、redo日志到底怎么操作才达到上述结果?我们接着看下面的案例

事务案例

把部门编号10的MANAGER员工调往部门编号20的部门,其它岗位的员工调往编号为30的部门,然后删除编号10的部门

上面业务,只需要1条update、一条delete就可以完成,而且这两个sql语句是要么全都执行成功,要么全都执行失败。要想实现这个效果,两条sql必须要在同一个事务下才行。这个还需要用到手动管理事务, 如下图
事务机制主要是利用undo、redo日志?

  1. 开启事务
  2. 执行update语句之前,把要修改的数据拷贝到undo日志里
  3. 再去执行update语句,并把结果记录到redo日志
  4. delete语句执行前,依然先把要执行的记录拷贝到undo日志
  5. 把删除的记录记录到redo日志
  6. 没有问题就可以提交事务,让redo日志把数据同步到数据文件里,假设发生宕机重启, 重启后,
    1. 想继续执行事务,可以把redo里剩余的记录继续同步到数据文件
    2. 不要继续执行事务,想回滚,可以把undo日志里的文件恢复到数据文件

再举个例子,假设商品秒杀,虽然抢到商品,但是没有来得及支付,那么这个事务回滚不能提交。这个对于mysql非常简单,只需要把undo、redo日志中当前事务的临时数据做一个标记,那么这个事务的日志就不会同步到数据文件

事务的ACID特性

事务机制主要是利用undo、redo日志?

事务的原子性

  • 一个事务中的所有操作要么全部完成,要么全部失败。事务执行后,不允许停留在中间某个状态

和用户的并发执行读写没有关系

事务的一致性

  • 不管在任何给定的时间、有多少个事务在执行,事务必须保证运行结果的一致性,不会出现歧义

和用户的并发执行读写有关系

举个例子,a、b、c、d四个人银行账号都存着500块,在某个时刻相互转账,如下图

事务机制主要是利用undo、redo日志?
不管四个人怎么转账,四个人的余额加起来应该是2000块,不能出现某个时刻加起来不是2000元而是2500元,试想真的这样,我们就可以通过这个漏洞赚钱了

事务是如何实现一致性的呢?
其实就是阻止事务之前相互读取临时数据,比如

  1. A账户是500块,它给B转账了10块,A的现在余额应该是490,这时候事务还没有提交
  2. 这时有人给A转账100块,那么把A账号的余额修改成了490+100=590元,然后去提交事务
  3. 这时候再看A转给B的10块钱,如果回滚了,不去同步操作,那这时A账户的余额是590元,而实际应该是600元才对。

如果事务之间能相互读取到没有提交的临时数据,真的就是凭空少了10块钱。
为了不出现歧义的数据,mysql事务之间是完全隔离的,也就是事务在undo、redo临时文件中保存的临时数据都是有归属的,一个事务不能读写其它事务保存的日志数据

事务的隔离性

  • 隔离性要求事务不受其他事务的影响,默认情况下事务A,只能看到日志中该事务的数据

事务机制主要是利用undo、redo日志?
每个事务只能看到相关的临时数据,别的事务的临时数据是看不到的, 从机制上看是事务的隔离性,从结果上看是事务的一致性

事务的持久性

  • 事务一旦提交,结果便是永久性的。即便发生宕机,仍然可以依靠事务日志完成数据的持久化

引申

单节点的MySQL数据库事务机制依靠的是undo、redo日志,如果再数据库集群中,我们修改了A节点MySQL的数据,然后在B节点的MySQL里添加了新的数据,我们怎么能够让这两个节点的事务联合成一个分布式事务呢?这就需要分布式事务