场景
某表users已有数据上千万,或者由于有很多text字段存入大量内容,导致表大小达到TB级,我们再直接给该表新加字段时候,很长时间都加不上(实际操作过2个小时加不上一个字段),甚至表被锁死
注意:
- 在业务低峰期做,将影响降到最低, 能停机做更好
- 删除索引后再修改表结构,效率将大大提升
解决方案:
- 思路1:建一个和该表一样的新表,给新表添加好字段,再将老表数据导入到新表, 在Navicat操作就行
- 具体操作:
# 生成新表
create table new_users like users;
## 生成删除索引语句
SELECT CONCAT('ALTER TABLE ',i.TABLE_NAME,' DROP INDEX ',i.INDEX_NAME,';') FROM INFORMATION_SCHEMA.STATISTICS i WHERE TABLE_SCHEMA = '库名' AND TABLE_NAME='users' AND i.INDEX_NAME != 'PRIMARY';
## 生成添加索引语句
SELECT CONCAT('ALTER TABLE ',i.TABLE_NAME,' ADD INDEX ',i.INDEX_NAME,'(',i.COLUMN_NAME,');') FROM INFORMATION_SCHEMA.STATISTICS i WHERE TABLE_SCHEMA = '库名' AND TABLE_NAME='users' AND i.INDEX_NAME != 'PRIMARY';
### 删除新表索引
ALTER TABLE new_users DROP INDEX product_id;
### 新表添加字段
alter table new_users add content text;
alter table new_users add seperate_type int(11) DEFAULT 1;
## copy数据
insert into new_users(字段1, 字段2, 除了created_at和updated_at字段, ......) select 字段1, 字段2, 除了created_at和updated_at字段, ...... from users;
如果有字段和数据库保留字符冲突,例如desc, 则用`desc` 表示
#有被锁的话就解锁
UNLOCK TABLES;
## 删除旧表
drop table users;
如果有外键影响,删不掉,SET FOREIGN_KEY_CHECKS=0; DROP TABLE variables; SET FOREIGN_KEY_CHECKS=1;
## rename新表
rename table new_users to users;
## 添加索引 3min+
ALTER TABLE users ADD INDEX index_users_product_id(product_id);
- 思路2:使用pt-online-schema-change
1.介绍:
pt-online-schema-change是percona公司开发的一个工具,在percona-toolkit包里面可以找到这个功能,它可以在线修改表结构
2.原理:
- 首先它会新建一张一模一样的表,表名一般是_为前缀_new后缀,例如原表为t_user 临时表就是_t_user_new
- 然后在这个新表执行更改字段操作
- 然后在原表上加三个触发器,DELETE/UPDATE/INSERT,将原表中要执行的语句也在新表中执行
- 最后将原表的数据拷贝到新表中,然后替换掉原表
使用:
没用过,具体上网查