背景介绍:
服务器 252GMem 40CPU SSD盘
小编所使用的mysql版本是5.6.25
mysql> select count(*) from CISXX_DATA_XXX;
+-----------+
| count(*) |
+-----------+
| 110908162 |
+-----------+
1 row in set (1 min 27.38 sec)
mysql> desc CISXX_DATA_XXX;
…
82 rows in set (0.01 sec)
第一次尝试直接加索引
mysql> alter table CISXX_DATA_XXX add column `RESERVED1` varchar(20) NOT NULL DEFAULT ‘‘ COMMENT ‘预留字段1‘,
-> add column `RESERVED2` varchar(20) NOT NULL DEFAULT ‘‘ COMMENT ‘预留字段2‘,
-> add column `RESERVED3` varchar(20) NOT NULL DEFAULT ‘‘ COMMENT ‘预留字段3‘;
ERROR 1878 (HY000): Temporary file write failure.
由于表太大,产生的临时表已经超出了 /目录下的磁盘限制。
第二次尝试新建表
修改新表结构,然后通过insert….select….方式导入数据
create table tmp_CISXX_DATA_XXX_20160620 (
……
);
insert into tmp_CISXX_DATA_XXX_20160620(
….
)select
…
from CISXX_DATA_XXX;
在数据导入的过程中,新开一个会话。测试本次建表过程对cis_data_tag表加的是什么锁。测试结果如下图:
由此可知,通过这种方式给cis_data_tag加的是一个共享锁。
在数据导入的过程中
服务器的负载如下:
磁盘读写压力情况:
在导数过程中发现/目录下的磁盘空间还是报警了
于是kill掉导数进程,执行kill掉操作后,发现服务器上的内存和磁盘使用率还是在不断上涨。于是再次尝试kill。再次尝试还是失败。小编意识到问题可能严峻了。如果系统资源一直这么消耗小去,会不会导致服务器挂机。oh no,这可是主库啊,要是挂机的话就意味着会影响生产业务。现在最主要的是要停止这恐怖的导数操作。正在小编想办法的时候,发现内存和磁盘空间资源开始释放。估计是和第一次尝试一样。但磁盘空间到达100%时,该导数进程就被服务器给终止掉了。
第三次尝试修改:
在第二尝试的基础上,小编是不会再在主库上执行这种操作了,同时意识到要操作的表实在太大。而/的磁盘空间又实在太小,必须要更改mysql临时空间的设置。于是整理了如下的解决方案
检查修改前中
内存的使用率一直在上涨,增长了72G
临时目录所在磁盘目录一直在上涨,增长了72G
磁盘的读写率达到了589836.00 wsec/s 172812.00 rsec/s
该表所占的物理文件大小也就48G
在建索引的过程中,小编发现,现在mysql居然支持在线DDL操作,即不会堵塞其它请求。请看:
这真的是个非常非常伟大的发现,mysql果然进步了。但是听说mysql只有部分表结构的修改是支持在线的,真是遗憾。
翻阅官方文档,可以了解更详细的信息:
参考链接:http://dev.mysql.com/doc/refman/5.7/en/innodb-create-index-overview.html
修改一张2千万的表添加字段和加索引所需的时间参考:
修改一张一亿的表添加字段和加索引所需的时间参考: