最近一个统计系统的大表需要加字段,表的引擎是myisam,表大小在3亿,物理文件在106G。想想都蛋疼。那么这种情况下怎么把字段撸上去呢?

1. 首先想到了《高性能MySQL》提到的直接更改表结构文件(frm),但是在经过测试以后,发现提示表损坏了,需要repair,只好放弃了。

2. 使用pt-online-schema-change,刚开始跑没有问题,后面在凌晨发现影响业务了,也只好放弃了。

3. 最近GitHub开源的gh-ost,属于新鲜玩意,还没有研究,只好放弃。

4. 创建新表,load数据,最后rename表。(前提是表只有insert,表是myisam引擎)

最后使用了第四种方案把字段加上了。那么下面就来详细说说第三种方案。

我们假设要把tb_yayun表加两个字段,uid,age。

老表(业务在使用的表):

mysql> show create table tb_yayun\G
*************************** 1. row ***************************
Table: tb_yayun
Create Table: CREATE TABLE `tb_yayun` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(20) DEFAULT NULL,
`enter_time` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `enter_time` (`enter_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

环境准备:

1. 一台空闲的服务器,没跑业务,安装了mysql实例的。在该服务器上面创建新表。

mysql> show create table tb_yayun_new\G
*************************** 1. row ***************************
Table: tb_yayun_new
Create Table: CREATE TABLE `tb_yayun_new` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` char(20) DEFAULT NULL,
`enter_time` datetime NOT NULL,
`uid` int(11) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `enter_time` (`enter_time`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

2. 在线上服务器导出tb_yayun表的数据(这里有一个技巧,不需要全部导出,截止到某一天就行。)可以用下面下面命令:

mysql -uroot -p -q -s -e "use test;select *,'','' from tb_yayun where enter_time >= '2016-08-01 00:00:00'" > /data/tb_yayun.txt

3. 把导出的文件拷贝到上面提到的空闲服务器导入(时间会很长,我当时导入3亿的表花了6小时):

LOAD DATA INFILE '/data/tb_yayun.txt' INTO TABLE tb_yayun_new;

4. 和开发确定一个切换时间;我们的数据都是先入队列,所以是可以暂停一会儿写入的。和开发确定好一个时间以后,比如要在2016-08-02 15:00:00以后切换,那么此时还需要做下面工作。还需要补一次数据,因为新表的数据只导入到了2016-08-01 00:00:00。所以再次从线上服务器导数据。

 mysql -uroot -p -q -s -e "use test;select *,'','' from tb_yayun where enter_time >= '2016-08-02 00:00:00' and enter_time <= '2016-08-02 15:00:00' > /data/02_tb_yayun.txt

再次拷贝到空闲的服务器导入:

 LOAD DATA INFILE '/data/02_tb_yayun.txt' INTO TABLE tb_yayun_new;

5. 当导入完成以后,把tb_yayun_new表的物理文件拷贝到线上服务器。(MYD,MYI,frm),注意权限。如果线上有1主3从,那么4台服务器都需要拷贝。拷贝完成以后执行flush tables,然后每台服务器检查表是否正常。limit一下或者count一下都行。

6. 通知开发停止写入,一般是把程序停止一会儿。具体时间不会超过10分钟。当开发说已经停了导入数据的程序以后,我们要看看老表是否还有数据写入,对于myisam表来说直接count看条数是否有变化就行。如果没有数据写入以后。执行下面的命令:

(1)再次从老服务器导数据,我们需要把数据补一致。(线上服务器)

mysql -uroot -p -q -s -e "use test;select *,'','' from tb_yayun where enter_time >= '2016-08-02 15:00:00' > /data/15_tb_yayun.txt                        

(2)load数据到tb_yayun_new(注意:会导致从库延时,具体延时多久看导入的数据大小)

LOAD DATA INFILE '/data/15_tb_yayun.txt' INTO TABLE tb_yayun_new;

(3)对比新表老表数据是否一致。如果操作没有错误的话,数据肯定是一致的。新表(tb_yayun_new),老表(tb_yayun)进行count确认。
(4)老表进行rename操作

alter table tb_yayun rename to tb_yayun_old_20160802; 

(5)新表rename操作

alter table tb_yayun_new rename to tb_yayun;

7. 通知开发那边开启数据导入程序。至此大表加字段完成。

总结:

上面提到的方法有非常大的局限性,比如必须是myisam表,该表只有insert,还有就是业务能够忍受5-10分钟没有最新数据。对于前台业务当然无法忍受,不过如果是公司的统计系统,或者内部人员使用。则完全没问题,影响非常小,沟通到位就行。

MyISAM表加字段的特殊方法的更多相关文章

  1. 关于Oracle.ManagedDataAccess数据库表加字段后,必须重启的问题

    关于Oracle.ManagedDataAccess数据库表加字段后,必须重启的问题,解决方法如下:在数据库连接字串中,增加一个参数:Metadata Pooling=false如“Data Sour ...

  2. MySQL锁(二)表锁:为什么给小表加字段会导致整个库挂掉?

    概述 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持.最常使用的MYISAM与INNODB都支持表级锁定.表级锁定分为表共享 ...

  3. MySQL如何安全的给小表加字段

    MySQL学习笔记-如何安全的给小表加字段 如果要给一个大表加字段,你一般都会非常谨慎小心,以免对线上业务造成影响,但实际上给一个小表加字段不慎操作也会导致线上业务出问题,这篇文章主要学习一下MySQ ...

  4. 获取sqlserver数据库中所有库、表、字段名的方法

    获取sqlserver数据库中所有库.表.字段名的方法 2009年03月12日 星期四 下午 12:51 1.获取所有数据库名: SELECT Name FROM Master..SysDatabas ...

  5. ecshop中user.php中的$user说明---user表加字段

    今天想对user表加个字段,打开user.php发现有个$user,其中它有很多方法,像登陆,注册,退出.都要用到它.可找了大半天也找不到这个函数调用的是哪个类.又坚持找了半天,发现$user在ini ...

  6. SQL多表多字段比对方法

    目录 表-表比较 整体思路 找出不同字段的明细 T1/T2两表ID相同的部分,是否存在不同NAME 两表的交集与差集:判断两表某些字段是否相同 两表的交集与差集:找出T2表独有的id 字段-字段比较 ...

  7. MySQL 笔记整理(6) --全局锁和表锁:给表加个字段怎么有这么多阻碍

    笔记记录自林晓斌(丁奇)老师的<MySQL实战45讲> 6) --全局锁和表锁:给表加个字段怎么有这么多阻碍 数据库锁设计的初衷是处理并发问题.作为多用户共享的资源,当出现并发访问的时候, ...

  8. Mysql实战45讲 06讲全局锁和表锁:给表加个字段怎么有这么多阻碍 极客时间 读书笔记

    Mysql实战45讲 极客时间 读书笔记 Mysql实战45讲 极客时间 读书笔记 笔记体会: 根据加锁范围:MySQL里面的锁可以分为:全局锁.表级锁.行级锁 一.全局锁:对整个数据库实例加锁.My ...

  9. MySQL8.0大表秒加字段,是真的吗?

    前言: 很早就听说 MySQL8.0 支持快速加列,可以实现大表秒级加字段.笔者自己本地也有8.0环境,但一直未进行测试.本篇文章我们就一起来看下 MySQL8.0 快速加列到底要如何操作. 1.了解 ...

随机推荐

  1. MySQL主从复制(Master-Slave)与读写分离(MySQL-Proxy)实践

    主服务器上(注:应该是允许从机访问)  GRANT REPLICATION SLAVE ON *.* to ‘rep1’@’192.168.10.131’ identified by ‘passwor ...

  2. Python与Hack

    1.Python的函数:关键字def()表示函数开始,可以在括号内填写任何变量,然后这些变量会被以引用的方式传递给函数,也就是说,函数内对这些变量的任何改变都会影响它们在主调函数中的值: 2.迭代:用 ...

  3. 解决Kali Linux没有声音

    解决Kali Linux没有声音   Kali Linux系统默认状态下,root用户是无法使用声卡的,也就没有声音.启用的方法如下: (1)在终端执行命令:systemctl --user enab ...

  4. Mac 自带 apache

    1.启动服务器 sudo apachectl start http://localhost   能访问就ok sudo apachectl stop sudo apachectl restart ht ...

  5. Linux 积累

    Unable to locate package 解决办法: sudo apt-get update

  6. WPF:在ControlTemplate中使用TemplateBinding

    A bit on TemplateBinding and how to use it inside a ControlTemplate. Introductio Today I'll try to w ...

  7. poj2386(简单dfs)

    就是求图中有多少个水洼.对图进行dfs遍历,并把是水洼的地方全部标记.然后从下一个是水哇的地方再进行dfs. #include <cstdio> #include <iostream ...

  8. NHibernate 中删除数据的几种方法

    今天下午有人在QQ群上问在NHibernate上如何根据条件删除多条数据,于是我自己就写了些测试代码,并总结了一下NHibernate中删除数据的方式,做个备忘.不过不能保证囊括所有的方式,如果还有别 ...

  9. django 安装

    git clone https://github.com/django/django.git 或者到django的官网下载 然后 python setup.py install

  10. java语言特性概述

    一.前言 我们都知道java是面向对象的编程,其中四个基本特性:抽象.封装.继承.多态.这四个特性,概括起来可以这么理解,抽象.封装.继承是多态的基础,多态是抽象.封装.继承的表现. 二. JAVA ...