背景
基础交易数据库trade_base使用的是mysql数据库,有两张大表trade_base_order 和 trade_base_resource_change_record,数据量分别达到了187G和258G,达到了总磁盘的81%,由于磁盘告警阀值设置在85%,加上数据主要集中在两张大表,导致了发现问题的时候已经无法增加索引和字段还有整块磁盘快耗尽的问题,mysql普通的delete无法释放磁盘空间,执行optmize table来释放磁盘空间也不行,因为剩余空间不够这个命令执行的要求,因此事情变稍微有点麻烦。
备选方案
方案一:换大容量的磁盘,这个方案的问题是需要停服
方案二:rename换表,这个方案的问题是数据同步期间的数据不一致
方案三:应用服务逻辑分库分表,这个方案的问题是需要开发资源,复杂性高,落地时间较长
业务分析
这个服务的定位主要是一个资源网关,本身没有太多逻辑,主要是代理一下底层资源系统,附加一些简单的安全控制逻辑,相当于底层资源系统的防腐层。这个服务的数据主要是写记录,对历史数据的依赖很少。底层资源系统本身做了严格的防重,因此这个服务逻辑上能够容忍短暂的数据不一致。
落地方案
基于业务分析及与个相关部门沟通最终采用了方案二,停服的代价较大,业务不太愿意,否决了方案一,方案三主要是时间来不及,也不想搞这么复杂。
执行步骤
1、创建好备份表名,此时备份表为空表
create table trade_base_request_20210127 like trade_base_request;
create table trade_base_order_20210127 like trade_base_order;
create table trade_base_resource_change_record_20210127 like trade_base_resource_change;
2、2021-01-27日10:00先将create_time>='2021-01-24:10:00:00' and create_time<='2021-01-27:10:00:00'数据插入到备份表
insert into trade_base_request_20210127 select * from trade_base_request_20210127
where create_time>='2021-01-24:10:00:00' and create_time<='2021-01-27:10:00:00';
insert into trade_base_order_20210127 select * from trade_base_order_20210127
where create_time>='2021-01-24:10:00:00' and create_time<='2021-01-27:10:00:00';
insert into trade_base_resource_change_record_20210127 select * from trade_base_resource_change_record_20210127
where create_time>='2021-01-24:10:00:00' and create_time<='2021-01-27:10:00:00';
3、互换表名,新表为插入三天的数据,服务写入新表,备份表中为历史数据 (命令执行毫秒级锁表)
RENAME TABLE trade_base_request TO backup_table,
trade_base_request_20210127 TO trade_base_request,
backup_table TO trade_base_request_20210127 ;
RENAME TABLE trade_base_order TO backup_table,
trade_base_order_20210127 TO trade_base_order,
backup_table TO trade_base_order_20210127 ;
RENAME TABLE trade_base_resource_change TO backup_table,
trade_base_resource_change_record_20210127 TO trade_base_resource_change,
backup_table TO trade_base_request_20210127 ;
4、 从备份表中抽取2021-01-27日10:00后的数据(create_time>2021-01-27:10:00:00)插入新表,大概3s左右完成。(忽略唯一索引冲突)
insert ignore into trade_base_request select * from trade_base_request_20210127 where create_time>'2021-01-27:10:00:00';
insert ignore into trade_base_order select * from trade_base_order_20210127 where create_time>'2021-01-27:10:00:00';
insert ignore into trade_base_resource_change_record select * from trade_base_resource_change_record_20210127 where create_time >='2021-01-27:10:00:00';
5、从备份表中抽取最近一个月的数据插入新表(已经插入的三天数据除外)
insert into trade_base_request select * from trade_base_request_20210127
where create_time>='2020-12-27 00:00:00'
and create_time<='2021-01-24:10:00:00';
insert into trade_base_order select * from trade_base_order_20210127
where create_time>='2020-12-27 00:00:00'
and create_time<='2021-01-24:10:00:00';
insert into trade_base_resource_change_record select * from trade_base_resource_change_record_20210127
where create_time>='2020-12-27 00:00:00'
and create_time<='2021-01-24:10:00:00';
6、检查一个月数据正常插入后drop掉备份表,释放空间。
drop table trade_base_request_20210127;
drop table trade_base_order_20210127;
drop table trade_base_resource_change_record_20210127;
实施效果
从问题发现到方案落地耗时3天,结果还算满意,没有出现大问题,成功释放了磁盘空间,及时满足了需要增加字段的需求。
问题
换表的时候造成一批数据库连接异常的情况,导致了多个业务反馈观察到一波服务响应超时的问题,不过好在事先有让业务方排查确认补偿逻辑,因此都在掌控之内,业务最终都自动补偿成功。
版权声明:本文为chenyun19890626原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。