第7章 事务
事务是数据库区别与普通文件系统的重要特性之一.
事务会把数据库从一种一致状态装换为另一种一致状态.在数据库提交工作时,要么确保所有修改都已经保存了,要么所有的修改都不保存.
1. 认识事物
(1). 概述
数据库的四大特性ACID:
- 原子性(atomicity):事务对外部不可分离,只有两种状态,成功或者失败.
- 一致性(conststency):把数据库从一种一致状态装换为另一种一致状态,前后完整性不被破坏(事务内动作符合要求,否则回滚)
- 隔离性(isolation):两个事物之间按照隔离级别有不同程度的不可见
- 持久性(durability):一旦提交,事务中对数据的修改永久保存
MySQL事务:实时更新缓冲区中的数据,事务提交时(或者不定时),会刷新到到磁盘持久化.如果发生宕机会使用redo日志从checkpoint(已经刷新到磁盘的标记)重做,发生回滚会根据undo中的老版本数据
(2). 分类
事务可以分为一下几种:
- 扁平事务:我们平常见到的事务,主要限制是不能控制提交或者回滚一部分数据
- 带保存点的扁平事务:保存点可以分阶段的回滚事务.缺点是宕机丢失,如果事务还是过久,不易恢复.
- 链事务:将保存点替换为事务的提交和下一个事务的开启合并为一个原子操作,并将必要的上下文传递下去.与带保存点的扁平事务相比,只能退回到最近的保存点.
- 嵌套事务:顶层事务控制子事务,子事务还有子事务.子事务可以提交和回滚,但不会立刻执行,当父事务提交时,进行处理.那么意味着只有顶层事务提交,所有的子事务才真正提交事务.
- 分布式事务:多台数据库客户端共用一个事务.
InnoDB存储引擎支持前三种事务.
2. 事务的实现
(1). redo
1). 基本概念
重做日志,用来实现事务的持久性,记录了文件物理上的变化,即对数据的修改.
由两部分组成,一个是内存中的重做日志缓冲,二是重做日志文件,是持久的.
事务提交时,现将所有日志写入重做日志进行持久化,然后才算提交完成.
每次重做日志缓冲写入重做日志文件时,InnoDB存储引擎都会调用依次fsync操作.
数据库中还有一种二进制日志文件,是在MySQL数据库的上层产生的,记录了每一条执行的SQL语句,使用二进制的方式存储.并且只在事务提交完成后一次性写入
当事务提交时,log buffer中一半空间被使用时,log Checkpoint时,log Buffer会将内存中的log block写入日志文件中.
2). log block
重做日志缓存,重做日志文件都是以款进行保存的,一个块的大小为512字节,被称为重做日志块(redo log block).
如果一个页中产生的重做日志数量大于一个日志块,那么将分割为多个日志块进行保存.
日志块中分为,日志头,日志本身和日志尾巴,三部分大小分别为12 + 492 + 8 = 512B.
3). log group
重做日志组,InnoDB实际上只有一个log group.
一个log group有多个重做日志文件组成,每个日志文件大小相同.
log group中的第一个重做日志文件中的前2KB部分(4个块)存储了log file header, Checkpoint1, 空, Checkpoint2.检查点的值交替写入,避免引介质失败导致找不到可用的检查点.
4). 重做日志格式
重做日志格式是基于页的,头部:
- redo_log_type:重做日志类型
- space:表空间的ID
- page_no:页的偏移量
- redo log body:根据类型不同,存储不同的内容.
5). LSN
全称Log Sequence Number,代表日志序列号,表示的含义有重做日志写入的总量,Checkpoint的位置,页的版本.
LSN本身即表示重做日志写入的总量,单位为字节.
每一个页的头部记录了该页的LSN值,表示该页最后刷新时LSN的大小,数据库启动时,检测到重做日志中的LSN如果与页中的LSN不同,那么意味着需要进行恢复.
6). 恢复
**InnoDB存储引擎不论上次数据库运行时是否是正常关闭,在启动时都会尝试进行恢复.**重做日志记录的是数据的物理变化,所以恢复起来非常快,不存在效率问题.
Checkpoint表示已经刷新到磁盘上的LSN,因此恢复过程中仅仅恢复Checkpoint之后的redo日志即可.
(2). undo
带有逻辑的原版本数据.
MySQL数据库的数据还包括一些隐含信息:隐含的自增id(在没有主键的时候代替主键),事务id,回滚id和delete flag.回滚id指向上一个版本的undo页.事务在进行回滚时根据事务id判断是否是当前事务造成的修改.
1). 基本概念
当需要进行回滚操作时,由于数据库内存中的数据都是实时更新的,所以需要记录原版本的数据以供回滚数据使用.
undo log中记录了不同版本的数据,并且是带有逻辑的(逻辑体现在修改时条件筛选等等).
undo log存放在数据库内部的一个特殊的段中,也就是undo段.位于共享表空间内.
2). undo存储管理
128个回滚段中,每个段有1024个undo页,每个页对应一个事务.也就是说,InnoDB支持的最大事务数量为128*1024个.
当事务提交时,undo log会被放入一个链表中,供之后进行purge操作(判断是否有其他事物使用undo页,如果没有,删除),如果这个undo页是可以重用的(已使用空间小于3/4),那么可以分配给下一个事务使用.
3). undo log格式
insert undo log是insert过程中产生的undo log. insert操作只对当前事务有效(其他事物不可见,并且insert是没有旧数据的),那么insert undo log在事务提交后直接删除.
update undo log是对delete和update操作产生的undo log.这种类型的undo log可能需要**提供MVCC机制**(作为记录链使用),所以不能直接删除.
(3). purge
delete和update操作并不能立刻删除原有数据.而是必须等待purge最终完成数据的更改(在此之前下标记,delete flag = 1,update和delete都使用insert和delete来代替).因为InnoDB存储引擎支持MVCC,所以需要保存原有数据.
(4). MVCC
(5). group commit
刷新缓冲到磁盘相比写入日志缓冲是一个很慢的过程.当前数据库都提供了group commit功能,即一次fsync可以刷新多个事务日志到写入文件.
一个事务刷新缓冲时,其他事务可以将其日志写入缓冲,然后一同写入文件.
来源:CSDN
作者:Benjamin-__
链接:https://blog.csdn.net/Benjalin_76_84/article/details/104214544