MySQL如何减少delete操作对undo的空间占用

利用行记录里的固定 5 字节的记录头信息里的 deleted_flag 标志位实现了 delete操作减少对 undo 空间的占用:

deleted_flag:在删的时候,只是把 deleted_flag 删除标志位改成 1、表示已被删除,等着 purge 线程会去看这个标志位,如果为 1、就清空了,如果是未提交的事务不会被清除。对于未提交的删除信息,其他可以继续 select,因为是未提交的,这时候不需要去读 undo 了,因为数据还没真正删除,直接去读那个数据块就可以了。MySQL delete 时大幅减少 undo 的使用。

假设删了一行,但是对应的事务并没有提交,deleted_flag 标志变成 1、表示已删除,但数据并没有真的删除,这时候 select 还可以看这行数据,实现了未提交事务的一致性读。这样就不用去 undo 里面读了。

原来的时候理解是:数据删了,找的时候去 undo 里面找原来的数据+数据块得到,其实不是这样的。所以 delete 的时候用到的 undo 的情况就比较少了, 减少了 undo 的使用。对于 MySQL 来说,delete 时用到的 undo 很少,对于 oracle来说,delete 操作会产生大量的 undo

next_record:页中下一条记录的相对位置,方便 IOT 表中一行行往下扫描数据。

2 个隐藏列:事务ID列(6 字节)和回滚指针列(7 字节)

事务的计数器:

我们开始一个事务,这个事务会被分配一个事务 id 1716486 

系统事务表:

ibdata 里的第五个页,分别执行 undo 表空间的 undo 段(段头页(事务开始后,里面有很多事务槽,拿出空事务槽把事务 id 写进去)+undo 页)

回滚表空间

回滚段

事务

 

rollback 的过程:

1、一个事务开始,生成一个事务 id(找事务 counter

2、读取系统事务表,找到一个回滚段(找相对空闲的),读取回滚段的段头块 (段头里面有很多行,找到其中空闲的行,把事务 id 写进去,写进去之后一个事务就开始了,一个事务槽盛放一个事务 id,也就是说一个事务开始了需要找到事务槽把事务 id 写进去)和一些回滚页(事务数据块)(我要修改一个数据行, 在数据行里需要把事务 id 写进去,在后面找一个 undo 块盛放修改前的数据),rollpointer(回滚指针)指向盛放旧数据的最后一个 undo 块,最后一个块指向前一个块,都链起来。当回滚的时候,先找到最后一个 undo 块,依次往前逆着读,把脏数据块还原成原来的数据块。

猜你喜欢

转载自www.cnblogs.com/5945yang/p/11061686.html