您当前的位置: 首页 >  sql

小志的博客

暂无认证

  • 1浏览

    0关注

    1217博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Mysql——UPDATE操作对应的undo日志

小志的博客 发布时间:2021-11-13 21:43:55 ,浏览量:1

目录
    • 1、 UPDATE操作对应的undo日志
    • 2、不更新主键的情况
    • 3、更新主键的情况

1、 UPDATE操作对应的undo日志
  • 在执行update语句时,InnoDB对更新主键和不更新主键这两种情况有截然不同的处理方式。
2、不更新主键的情况

(1)、就地更新

  • 在更新记录时,对于被更新的每个列来说,如果更新后的列与更新前的列占用的存储空间一样大,那么可以进行就地更新,也就是直接在原记录的基础上修改对应列的值。

(2)、先删除旧记录,再插入新记录

  • 如果有任何一个被更新的列在更新前后占用的存储空间大小不一致,那么就需要先把这条旧记录从聚簇索引页面中删除,然后在根据更新后列的值创建一条新的记录并插入到页面中。

  • 这里的删除,是真正的删除,也就是把这条记录从正常记录链表中移除并加入到垃圾链表中。

  • 是由用户线程同步执行真正的删除操作,而不是DELETE语句中进行purge操作时使用的专门线程。

  • 如果新创建的记录占用的存储空间不超过旧记录占用的空间,那么可以直接重用加入到垃圾链表中的旧记录所占用的存储空间,否则,需要在页面中新申请一块空间供新记录使用。

  • 如果本页面已经没有可用的空间,就需要进行页面分裂操作,然后再插入新的记录。

  • 更新操作对应TRX_UNDO_UPD_EXIST_REC类型的undo日志结构,如下图所示: 在这里插入图片描述

  • 注:上图解释如下

  • info bits:记录头信息的前4个比特的值。

  • trx_id:旧记录的trx_id值。

  • roll_pointer:旧记录的roll_pointer值。

  • len of index_col_info:也就是下边的【索引列各列信息】部分和本部分占用的存储空间总和。

  • 索引列各列信息 列表:凡是被索引的列的各列信息。

  • n_updated:表示本条UPDATE语句执行后将有几个列被更新

  • 被更新的列更新前信息 列表:被更新列在记录中的位置、更新前该列占用的存储空间大小、更新前该列的真实值。

(3)、更新操作生成undo日志的示例

  • 先插入两条记录
# 显示开启一个事务,假设该事务的事务id为100
BEGIN;
# 插入两条记录
INSERT INTO sys_user(id, name, city) VALUES(1, 'xz','北京市'), (2, 'tom','天津市');
# 删除一条记录
DELETE FROM sys_user WHERE id = 1;
# 更新一条记录
UPDATE sys_user SET name='jack', city='上海市' where id = 2;

在这里插入图片描述

  • 上图解释说明
  • 这个UPDATE语句更新的列的大小都没有改动,所以可以采用就地更新的方式来执行。
  • 在真正改动页面记录前,会先记录一条类型为TRX_UNDO_UPD_EXIST_REC的undo日志。
  • 其中,占用空间等于:(1+1+4)+(1+1+3) =11,最后,再加上len of index_col_info属性本身占2个字节,所以总共13字节。即:len of index_col_info=13。
3、更新主键的情况
  • 步骤一:将旧记录进行delete mark操作 (1)、此时仅执行delete mark操作。而在事务提交后,才由专门的线程执行purge操作,从而把它加入到垃圾链表中。 (2)、之所以只对旧记录执行delete mark操作,是因为别的事务也可能同时访问这条记录,如果把它真正删除并加入到垃圾链表后,别的事务就访问不到了。这个功能就是MVCC。
  • 步骤二:根据更新后各列的值创建一条新记录,并将其插入到聚簇索引中 (1)、针对UPDATE语句更新记录主键值的这种情况,在对该记录进行delete mark操作时,会记录一条类型为TRX_UNDO_DEL_MARK_REC的undo日志;之后插入新记录时,会记录一条类型为TRX_UNDO_INSERT_REC的undo日志。也就是说,每对一条记录的主键值进行改动,都会记录2条undo日志。
关注
打赏
1661269038
查看更多评论
立即登录/注册

微信扫码登录

0.1038s