背景
公司使用的是MySQL数据库,随着业务和用户的增加有张表的数据达到了150000000(1亿5千万)条左右,其中好几个功能都会对这张表进行增删改操作。在并发量比较大的时候,经常会出现死锁问题。
为了解决这个问题找到CTO和其他领导来请教方案。
经过分析之后,由于离业务繁忙期还有几天,并且1月是系统达到最大并发的时期,所以决定暂时先采取比较稳妥的版本号方案,即只往数据库insert和update数据,定时任务删除旧的数据(之后会采取数据分表分区的方案)版本号记录在redis里面。于是花了2天左右的时间把这些业务里面的代码重构和修改了一遍(其中涉及到使用第三方库修改的代码,修改这部分花了很多时间)。经测试人员测试没问题后,准备发到线上。
过程
要刷入得的SQL如下:
ALTER TABLE xxx ADD COLUMN K_VERSION BIGINT(20) DEFAULT 0 COMMENT '版本号';
17年12月29日凌晨左右,运维开始执行sql。到1点多的时候,运维说数据库所在的服务器硬盘满了,导致刷入失败。里面有人开始议论说,不就是刷入字段吗,怎么会造成磁盘满呢?运维当时立马通过阿里云德后台把数据库的服务器磁盘增大。当时我的第一反应:肯定这个SQL在表数据量大的时候会有问题。搜索之后发现,当数据量很大的时候,会占大量的undo空间,同时还会锁表。所以要想解决问题必须分开执行sql 最后执行sql如下:
第一步:
ALTER TABLE xxx ADD COLUMN K_VERSION BIGINT(20) COMMENT '版本
第二步:
ALTER TABLE XXX MODIFY(K_VERSION DEFAULT 0);
第三步:
update table XXX set K_VERSION=0;
之后也没有出现刷sql挂服务器的问题。