rds mysql 修改百萬級大表的表結構


問題:對於百萬級或千萬級的大表,如果需求修改表結構。要怎么做??

 

1)一般不建議修改大表的數據結構,可以采用擴展表或其他辦法來解決業務問題。能不改就不改;

2)直接 ALTER TABLE 肯定是不行的~,ALTER TABLE 會鎖表,會影響業務的正常運行。

注:即使加了ALGORITHM = INPLACE, LOCK = NONE選項,不鎖表。對於大表的操作 ALTER TABLE 還是相當耗時、耗性能的,不建議直接使用這個操作

ALTER TABLE table_name ADD COLUMN field_name INT (11) UNSIGNED NULL DEFAULT 0 COMMENT '新字段', ALGORITHM = INPLACE, LOCK = NONE;

 


 

不能直接修改表的話,那要怎么做呢??下面是我最近更新線上某大表表結構的操作,內容僅供參與~

 

一、創建副表、修改副表表結構

CREATE TABLE new_table LIKE old_table;
ALTER TABLE new_table ADD COLUMN field_name INT (11) UNSIGNED NULL DEFAULT 0 COMMENT '新字段' AFTER xxx_field;

 

二、備份舊表數據

大數據的備份建議用 into outfile 命令來操作

SELECT * FROM old_table INTO OUTFILE '/temp/old_table_backup.txt';

1)先用 SHOW VARIABLES LIKE 'secure%'; 命令看一下有沒有 into outfile 和 load data 操作權限;沒有的話,得改一下mysql的配置;

注:當secure_file_priv,=null時表示沒有outfile和infile的權限,=temp(目錄名)時表示outfile只能輸出到這個目錄,=''時,outfile可以輸出到任意目錄~

2)上面命令有可能會報 ERROR 1045 (28000): Access denied for user 'xxx'@'%' (using password: YES) 錯誤;原因是當前mysql用戶沒有服務器目錄的寫權限(上面代碼是寫到/temp/目錄里);

 

注:能使用 outfile 命令的盡量使用 outfile 命令,outfile命令的性能消耗要低一點

 

如果沒有權限或者不想備份到服務器里,那怎么辦呢?我們可以用本地的mysqldump工具遠程連接導出數據到本地

mysqldump -h rr-xxxxxxxxxx.mysql.rds.aliyuncs.com -u webuser -t -f -p --set-gtid-purged=off --default-character-set=utf8 --skip-triggers --skip-lock-tables prod_xxx old_table > D:/backup/old_table.sql

注:-t 表示只要數據,不要結構;-f 表示忽略錯誤;--skip-triggers 表示跳過觸發器,--skip-lock-tables 表示不要鎖表

mysqldump 命令選項詳情:https://help.aliyun.com/knowledge_detail/41732.html?spm=a2c4g.11186631.2.13.2c047e53mfgl55

導出的時候,如果有從庫的話,要用從庫導出

 

三、刪除新表索引(很重要)

帶索引寫入會很慢、性能消耗高,要先刪除索引;網上用的 disable keys(禁用索引)親測無效,還是刪除索引吧。導入數據之后再重建索引;

ALTER TABLE `new_table` DROP INDEX `idx_xxx1`, DROP INDEX `idx_xxx2`, DROP INDEX `idx_xxx3`;

 

四、舊表數據導入到新表(如果是dump到本地的,本地建副表-》刪除索引-》source導入數據-》select ... outfile-》得到備份數據文件)

登錄遠程主庫(有寫入權限)

mysql -h rm-xxxx.mysql.rds.aliyuncs.com -u webuser -p
set names utf8;
use prod_xxx;

 

登錄並選擇好數據庫后,現在導出數據(這是導入到線上的新表,不是本地的~~)

load data local infile 'D:/backup/old_table.txt' ignore into table new_table(field1,field2...);

注:注意要加上 local 關鍵字,不然可能會報錯;

load data 命令詳情說明:https://help.aliyun.com/document_detail/127794.html?spm=5176.13910061.sslink.19.58d45a49ChoPv5

 

五、導入成功后,重新索引

ALTER TABLE `new_table` ADD INDEX `idx_xxx1` (`xxx1`) USING BTREE;
ALTER TABLE `new_table` ADD INDEX `idx_xxx2` (`xxx2`) USING BTREE;
ALTER TABLE `new_table` ADD INDEX `idx_xxx3` (`xxx3`) USING BTREE;

建議分開建多個索引。當然一次性創建多個也是可以的,可能會慢一點~

 

六、停止舊表的寫入 

停止寫入或找一個寫入少的時間

 

七、處理差異數據導入到新表

在我們處理數據的這段時間內,又有新數據寫入到報舊表

INSERT INTO new_table (field1, field2...) SELECT field1, field2... FROM old_table where id>=xxx

 

八、數據表重命名

ALTER TABLE old_table RENAME old_table_bak;
ALTER TABLE new_table RENAME old_table;

舊表改一個臨時名,新表改回舊表的表名~

 


 

到此,大表的結構修改就完成了。(已改臨時名的舊表看情況可以刪除掉~)完。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM