MyISAM表加字段的特殊方法
最近一個統(tǒng)計(jì)系統(tǒng)的大表需要加字段,表的引擎是myisam,表大小在3億,物理文件在106G。想想都蛋疼。那么這種情況下怎么把字段擼上去呢?
1. 首先想到了《高性能MySQL》提到的直接更改表結(jié)構(gòu)文件(frm),但是在經(jīng)過測試以后,發(fā)現(xiàn)提示表損壞了,需要repair,只好放棄了。
2. 使用pt-online-schema-change,剛開始跑沒有問題,后面在凌晨發(fā)現(xiàn)影響業(yè)務(wù)了,也只好放棄了。
3. 最近GitHub開源的gh-ost,屬于新鮮玩意,還沒有研究,只好放棄。
4. 創(chuàng)建新表,load數(shù)據(jù),最后rename表。(前提是表只有insert,表是myisam引擎)
?
最后使用了第四種方案把字段加上了。那么下面就來詳細(xì)說說第三種方案。
我們假設(shè)要把tb_yayun表加兩個字段,uid,age。
老表(業(yè)務(wù)在使用的表):
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)
環(huán)境準(zhǔn)備:
1. 一臺空閑的服務(wù)器,沒跑業(yè)務(wù),安裝了mysql實(shí)例的。在該服務(wù)器上面創(chuàng)建新表。
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. 在線上服務(wù)器導(dǎo)出tb_yayun表的數(shù)據(jù)(這里有一個技巧,不需要全部導(dǎo)出,截止到某一天就行。)可以用下面下面命令:
mysql -uroot -p -q -s -e "use test;select *,'','' from tb_yayun where enter_time >= '2016-08-01 00:00:00'" > /data/tb_yayun.txt3. 把導(dǎo)出的文件拷貝到上面提到的空閑服務(wù)器導(dǎo)入(時間會很長,我當(dāng)時導(dǎo)入3億的表花了6小時):
LOAD DATA INFILE '/data/tb_yayun.txt' INTO TABLE tb_yayun_new;4. 和開發(fā)確定一個切換時間;我們的數(shù)據(jù)都是先入隊(duì)列,所以是可以暫停一會兒寫入的。和開發(fā)確定好一個時間以后,比如要在2016-08-02 15:00:00以后切換,那么此時還需要做下面工作。還需要補(bǔ)一次數(shù)據(jù),因?yàn)樾卤淼臄?shù)據(jù)只導(dǎo)入到了2016-08-01 00:00:00。所以再次從線上服務(wù)器導(dǎo)數(shù)據(jù)。
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再次拷貝到空閑的服務(wù)器導(dǎo)入:
LOAD DATA INFILE '/data/02_tb_yayun.txt' INTO TABLE tb_yayun_new;5. 當(dāng)導(dǎo)入完成以后,把tb_yayun_new表的物理文件拷貝到線上服務(wù)器。(MYD,MYI,frm),注意權(quán)限。如果線上有1主3從,那么4臺服務(wù)器都需要拷貝。拷貝完成以后執(zhí)行flush tables,然后每臺服務(wù)器檢查表是否正常。limit一下或者count一下都行。
6. 通知開發(fā)停止寫入,一般是把程序停止一會兒。具體時間不會超過10分鐘。當(dāng)開發(fā)說已經(jīng)停了導(dǎo)入數(shù)據(jù)的程序以后,我們要看看老表是否還有數(shù)據(jù)寫入,對于myisam表來說直接count看條數(shù)是否有變化就行。如果沒有數(shù)據(jù)寫入以后。執(zhí)行下面的命令:
(1)再次從老服務(wù)器導(dǎo)數(shù)據(jù),我們需要把數(shù)據(jù)補(bǔ)一致。(線上服務(wù)器)
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數(shù)據(jù)到tb_yayun_new(注意:會導(dǎo)致從庫延時,具體延時多久看導(dǎo)入的數(shù)據(jù)大小)
LOAD DATA INFILE '/data/15_tb_yayun.txt' INTO TABLE tb_yayun_new;(3)對比新表老表數(shù)據(jù)是否一致。如果操作沒有錯誤的話,數(shù)據(jù)肯定是一致的。新表(tb_yayun_new),老表(tb_yayun)進(jìn)行count確認(rèn)。
(4)老表進(jìn)行rename操作
(5)新表rename操作
alter table tb_yayun_new rename to tb_yayun;?
7. 通知開發(fā)那邊開啟數(shù)據(jù)導(dǎo)入程序。至此大表加字段完成。
?
總結(jié):
上面提到的方法有非常大的局限性,比如必須是myisam表,該表只有insert,還有就是業(yè)務(wù)能夠忍受5-10分鐘沒有最新數(shù)據(jù)。對于前臺業(yè)務(wù)當(dāng)然無法忍受,不過如果是公司的統(tǒng)計(jì)系統(tǒng),或者內(nèi)部人員使用。則完全沒問題,影響非常小,溝通到位就行。
?
轉(zhuǎn)載于:https://www.cnblogs.com/gomysql/p/5747545.html
總結(jié)
以上是生活随笔為你收集整理的MyISAM表加字段的特殊方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何将cv::Mat类型转换为imgui
- 下一篇: 通过指针便利图像元素