暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

MySQL事务详解(四):原子性的保障——undo

IT的世界 2024-06-14
45

MySQL事务需要的满足的ACID原则,其中的I(隔离性,Isolation)
在文章MySQL事务详解(二):隔离级别的实现MVCCMySQL事务详解(三):脏写与幻读的绝路—锁已经详细学习过,通过MySQL的MVCC机制与锁机制来实现。
其中的C(一致性,Consistency)
的实现依靠数据库自身设定的规定和约束、程序员的业务代码实现来保证。
同时隔离性与原子性也是实现了一致性的一种手段。一致性是我们追求的最终的结果。
A(原子性,Atomicity)
依靠MySQL的undo来保证,D(持久性,Durability)
使用MySQL的redo来保障。
这篇文章我们先来学习下undo,redo在下次分享中再详细论述。

undo的场景与作用

原子性要保证事务中的操作要么全做,要么全不做
。但是事务的执行过程中,会遇到各种场景,导致事务中断:

  • • 执行过程中遇到系统故障
    服务器故障
    断电
    等不可控场景

  • • 执行过程中手动执行了rollback语句
    ,提前结束事务

上述场景中,事务可能执行了增删改操作,修改了记录,为了保证原子性,需要将修改的记录改回到原来的状态,使得数据库好像没发生变化一样,这个步骤叫回滚

为了记录修改前的记录
,需要将其写入到日志文件中,这个保存原来记录的日志,即undo log

undo log除了支持回滚数据
外,在MySQL事务详解(二):隔离级别的实现MVCC中提到过的版本链
也是通过undo log构成
所以undo log也是mvcc
中不可或缺的一部分。

undo的存储结构

undo log 通过回滚段(rollback segment)
进行管理的。每个回滚段由1024个undo slot
组成,这些undo slot里面存放的是undo链表
的第一个节点。如图:

如果在MySQL初始化时配置了undo表空间,那么回滚段就被分配到undo表空间
,否则分配到系统表空间

undo的类型

在MySQL的InnoDB引擎中,将undo log分为了两种类型:

  • • insert undo log : 对应于insert操作
    或者更新主键
    产生的undo log。

  • • update undo log : 对应delete和update操作
    产生的undo log。
    将undo 分为两种类型的原因
    在于:对于insert操作的记录,只对于本事务可见,事务提交后可以直接删除insert undo log

    对于update undo log,因为mvcc机制的需要,在事务提交后还需要保持一段时间,只能等待purge线程去删除

    所以如果一个事务同时包含着insert、delete、update操作,那么会产生不同类型的undo log。
    从而会在表空间的两个slot
    中生产两条不同的undo链表
    。如图

undo的写入过程

  1. 1. 事务对记录做更改之前,首先去表空间(系统表空间或者undo表空间)分配一个回滚段
    (轮询算法分配),一经分配该事务就不会再分配回滚段。

  2. 2. 分配到回滚段后,查询对应的缓存链表(insert/update)
    是否缓存了undo slot。如果有缓存则将缓存的undo slot 分配给该事务。

  3. 3. 如果没有缓存,则在回滚段中查找可用的undo slot
    分配给该事务。如果slot都不可用则直接报错

  4. 4. 分配到undo slot后,如果是从缓存链表中复用的,则可以直接使用。否则需要重新分配undo log segment
    ,并从中申请undo页
    写入到slot中

  5. 5. 分配完undo页后,事务将undo log 写入到对应的页面
    即可。

undo相关配置

mysql> show global variables like "%undo%";
+--------------------------+------------+
| Variable_name            | Value      |
+--------------------------+------------+
| innodb_max_undo_log_size | 1073741824 |
| innodb_undo_directory    | ./         |
| innodb_undo_log_truncate | OFF        |
| innodb_undo_logs         | 128        |
| innodb_undo_tablespaces  | 0          |
+--------------------------+------------+

innodb_max_undo_log_size
: 表空间的大小,默认1G。
innodb_undo_directory
: undo表空间的存储路径。如果没有指定,则在MySQL的数据目录创建。
innodb_undo_log_truncate
: 启用后,当表空间大小超过innodb_max_undo_log_size
,将会被截断。注意:启用时,innodb_undo_tablespaces必须大于等于2,innodb-rollback-segments必须大于等于35.
innodb_undo_logs
: 回滚段数量(5.7已弃用)。与 innodb_rollback_segments同意,默认128(也是最大值)。
innodb_undo_tablespaces
: 表空间大小。默认0(表示不开启undo 表空间),最大限制95。只可以初始化MySQL时指定。
innodb_purge_rseg_truncate_frequency
: 系统释放回滚段的频率,以调用清除的次数为单位。默认128。undo 表空间在回滚段被释放前不能被截断。

既然已经看到这里,请随手点个赞和“在看”吧。

欢迎关注我的公众号“IT的世界”,原创技术文章第一时间推送。


文章转载自IT的世界,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论