MyISAM表加字段的特殊方法

2021-09-08 19:01:48 字數 3735 閱讀 5700

最近乙個統計系統的大表需要加欄位,表的引擎是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

notnull,

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)

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分鐘沒有最新資料。對於前台業務當然無法忍受,不過如果是公司的統計系統,或者內部人員使用。則完全沒問題,影響非常小,溝通到位就行。

已有大量資料的表加字段的方法

如果乙個表中有大量的資料庫,增加欄位或增加字段長度,經常會彈出以下錯誤 超時時間已到,無法修改表 用以下方法可解決問題 增加字段 alter table 表名 add 字段 字段型別 例如 use ase order alter table dbo.t orderbase add remaronly...

rail 生成表 加欄位

建立表方法 rails generate model experts 在db migrate 2019 create experts.rb 檔案中,class createexperts activerecord migration def change create table experts d...

mysql給表的字段加索引

1 新增普通索引 alter table table name add index index name column 2 新增主鍵索引 alter table table name addprimary key column 3 新增唯一索引 unique alter table table na...