背景

update t_user_voucher set seller_support=0 where id in(select id from tmp_muvids_0311) limit 1;

最近同事在做重构,涉及数据迁移和数据修复,线上执行了这个语句。

阿里云就收到了报警:

云数据库RDS版 发生告警
时间: 15:13
实例名称: 线上mysql_8
实例详情: xxxx
监控指标: 磁盘使用率
报警条件: (80.99>80)
持续时间: 8小时4分钟

原因定位过程

  1. 最开始是以为有什么上线,导致数据增长比较多。所以问了下3个业务组最近有哪些上线。结果没有上上线。

  2. 因为我们线上是一主三从,然后一个同事发现, 只有主库报警,从库没有报警,主库磁盘占用 比 从库磁盘占用 多了60G。

  3. 然后阿里云提了工单,给我们看了mysql8数据库的数据库文件相关的信息

// 我做了一定处理
库	269G	no	
.库/表.ibd	14G
.库/表.ibd	13G

undo log存放的位置是

A: 好像是在.idb文件中??? TODO

// 附录6

InnoDB默认是将Undo-log存储在xx.ibdata共享表数据文件当中,默认采用段的形式存储

show variables like 'innodb_file_per_table';
说明线上为独占表空间

同时发现
show variables like 'innodb_undo_tablespaces';

然后参数innodb_max_undo_log_size为1073741824。

对于事务回滚原理的纠正

// 附录6

实际上当一个事务需要回滚时,本质上并不会以执行反SQL的模式还原数据, 而是直接将roll_ptr回滚指针指向的Undo记录,从xx.ibdata共享表数据文件中拷贝到xx.ibd表数据文件,覆盖掉原本改动过的数据。

如何处理巨大的回滚段? TODO

// 附录7

没啥好办法,大数据量,回滚就是很耗时。

可以考虑分批提交。

我们执行kill语句,发现不能kill。

// 参考附录3

_config.yml

参考

1.03 | 事务隔离:为什么你改了我还看不见?

1.1 回滚日志总不能一直保留吧,什么时候删除呢?

1.2 回滚段被清理,文件也不会变小? TODO 这是为啥

1.3 基于上面的说明,我们来讨论一下为什么建议你尽量不要使用长事务。 长事务意味着系统里面会存在很老的事务视图。由于这些事务随时可能访问数据库里面的任何数据,所以这个事务提交之前,数据库里面它可能用到的回滚记录都必须保留,这就会导致大量占用存储空间。

2.参考我之前博客

3.MySQL UNDO表空间独立和截断

4.万答#18,MySQL8.0 如何快速回收膨胀的UNDO表空间

5.32 | 为什么还有kill不掉的语句? 所以,如果你发现一个线程处于 Killed 状态,你可以做的事情就是,通过影响系统环境,让这个 Killed 状态尽快结束。

6.InnoDB默认是将Undo-log存储在xx.ibdata共享表数据文件当中,默认采用段的形式存储

7.MySQL的rollback–大事务回滚

原创文章转载请注明出处: update导致undolog膨胀,mysql磁盘占用膨胀 && kill不掉的语句