mysql大表不停机加字段_mysql大表在不停机的情况下增加字段该怎么处理
MySQL中给一张千万甚至更大量级的表添加字段一直是比较头疼的问题,遇到此情况通常该如果处理?本文通过常见的三种场景进行案例说明。
1、 环境准备
数据库版本: 5.7.25-28(Percona 分支)
服务器配置: 3台centos 7虚拟机,配置均为2CPU 2G内存
数据库架构: 1主2从的MHA架构(为了方便主从切换场景的演示,如开启GTID,则两节点即可),关于MHA搭建可参考此文 MySQL高可用之MHA集群部署
准备测试表: 创建一张2kw记录的表,快速创建的方法可以参考快速创建连续数
本次对存储过程稍作修改,多添加几个字段,存储过程如下:
DELIMITER $$CREATE PROCEDURE `sp_createNum`(cnt INT)BEGIN
DECLARE i INT DEFAULT 1;DROP TABLE if existstb_add_columns;CREATE TABLE if not exists tb_add_columns(id int primary key,col1 int,col2 varchar(32));INSERT INTO tb_add_columns(id,col1,col2) SELECT i as id ,i%7 as col1,md5(i) ascol2;WHILE i
INSERT INTO tb_add_columns(id,col1,col2) SELECT id + i as id ,( id + i) %7 as col1,md5( id + i) as col2 FROM tb_add_columns WHERE id <=cnt -i ;SET i = i*2;END;END WHILE;END$$
DELIMITER ;
调用存储过程,完成测试表及测试数据的创建。
mysql> call sp_createNum(20000000);
2. 直接添加字段
使用场景: 在系统不繁忙或者该表访问不多的情况下,如符合ONLINE DDL的情况下,可以直接添加。
模拟场景: 创建一个测试脚本,每10s访问该表随机一条记录,然后给该表添加字段
访问脚本如下:
#!/bin/bash
# gjcfor i in {..1000000000} # 访问次数1000000000,按需调整即可do
id=$RANDOM #生成随机数
mysql-uroot -p'123456' --socket=/data/mysql3306/tmp/mysql.sock -e "select a.*,now() from testdb.tb_add_columns a where id ="$id# 访问数据sleep # 暂停10sdone
运行脚本
sh test.sh
给表添加字段
mysql> alter table testdb.tb_add_columns add col3 int;
此时,访问正常。
附ONLINE DDL的场景如下,建议DBA们必须弄清楚
(图片转载于https://blog.csdn.net/finalkof1983/article/details/88355314)
(图片转载于https://blog.csdn.net/finalkof1983/article/details/88355314)
3. 使用工具在线添加
虽然Online DDL添加字段时,表依旧可以读写,但是生产环境使用场景中对大表操作使用最多的还是使用工具pt-osc或gh-ost添加。
本文主要介绍 pt-osc(pt-online-schema-change) 来添加字段,该命令是Percona Toolkit工具中的使用频率最高的一种
关于Percona Toolkit的安装及主要使用可以参考 五分钟学会Percona Toolkit 安装及使用
添加字段
root@mha1 ~]# pt-online-schema-change --alter "ADD COLUMN col4 int" h=localhost,P=,p=123456,u=root,D=testdb,t=tb_add_columns,S=/data/mysql3306/tmp/mysql.sock --charset=utf8mb4 --execute
主要过程如下:
> Cannot connect to A=utf8mb4,P=,S=/data/mysql3306/tmp/mysql.sock,h=192.168.28.132,p=...,u=root> Cannot connect to A=utf8mb4,P=,S=/data/mysql3306/tmp/mysql.sock,h=192.168.28.131,p=...,u=root
No slaves found. See--recursion-method ifhost mha1 has slaves. # 因为使用的是socket方式连接数据库 且未配置root远程连接账号,所以会有此提示
# A software update is available:
Operation, tries,wait:
analyze_table,, 1copy_rows,, 0.25create_triggers,, 1drop_triggers,, swap_tables,, update_foreign_keys,, Altering `testdb`.`tb_add_columns`...
Creating new table... # 创建中间表,表名为"_原表名_new"
Created new table testdb._tb_add_columns_new OK.
Altering new table... # 修改表,也就是在新表上添加字段,因新表无数据,因此很快加完
Altered `testdb`.`_tb_add_columns_new` OK.--20T12::Creating triggers... # 创建触发器,用于在原表拷贝到新表的过程中原表有数据的变动(新增、修改、删除)时,也会自动同步至新表中--20T12::Created triggers OK.--20T12:: Copying approximately 19920500rows... # 拷贝数据,数据库量是统计信息里的,不准确
Copying `testdb`.`tb_add_columns`:% :remain # 分批拷贝数据(根据表的size切分每批拷贝多少数据),拷贝过程中可以用show processlist看到对应的sql
Copying `testdb`.`tb_add_columns`:% :remain
Copying `testdb`.`tb_add_columns`:% :remain
Copying `testdb`.`tb_add_columns`:% :remain
Copying `testdb`.`tb_add_columns`:% :remain
Copying `testdb`.`tb_add_columns`:% :remain
Copying `testdb`.`tb_add_columns`:% :remain
Copying `testdb`.`tb_add_columns`:% :remain
Copying `testdb`.`tb_add_columns`:% :remain--20T12::Copied rows OK. # 拷贝数据完成--20T12::Analyzing new table... # 优化新表--20T12::Swapping tables... # 交换表名,将原表改为"_原表名_old",然后把新表表名改为原表名--20T12::Swapped original and new tables OK.--20T12::Dropping old table... # 删除旧表(也可以添加参数不删除旧表)--20T12::Dropped old table `testdb`.`_tb_add_columns_old` OK.--20T12::Dropping triggers... # 删除触发器--20T12::Dropped triggers OK.
Successfully altered `testdb`.`tb_add_columns`. # 完成
修改过程中,读写均不受影响,大家可以写个程序包含读写的
注: 无论是直接添加字段还是用pt-osc添加字段,首先都得拿到该表的元数据锁,然后才能添加(包括pt-osc在创建触发器和最后交换表名时都涉及),因此,如果一张表是热表,读写特别频繁或者添加时被其他会话占用,则无法添加。
例如: 锁住一条记录
用pt-osc添加字段,会发现一直卡在创建触发器那一步
此时查看对应的SQL正在等待获取元数据锁
换成直接添加也一样,例如
当达到锁等待后将会报错放弃添加字段
mysql> alter table testdb.tb_add_columns add col5 int;
ERROR1205 (HY000): Lock wait timeout exceeded; try restarting transaction
对于此情况,需等待系统不繁忙情况下添加,或者使用后续的在从库创建再进行主从切换
4 先在从库修改,再进行主从切换
使用场景: 如果遇到上例中一张表数据量大且是热表(读写特别频繁),则可以考虑先在从库添加,再进行主从切换,切换后再将其他几个节点上添加字段。
先在从库添加(本文在备选节点添加)
mysql> alter table testdb.tb_add_columns add col5 int;
Query OK,0 rows affected (1 min 1.91sec)
Records:0 Duplicates: 0 Warnings: 0
进行主从切换
使用MHA脚本进行在线切换
masterha_master_switch --conf=/etc/masterha/app1.conf --master_state=alive --orig_master_is_new_slave --new_master_host=192.168.28.131 --new_master_port=
切换完成后再对其他节点添加字段
/*原主库上添加192.168.28.128*/mysql> alter table testdb.tb_add_columns add col5 int;
Query OK,0 rows affected (1 min 8.36sec)
Records:0 Duplicates: 0 Warnings: 0
/*另一个从库上添加192.168.28.132*/mysql> alter table testdb.tb_add_columns add col5 int;
Query OK,0 rows affected (1 min 8.64sec)
Records:0 Duplicates: 0 Warnings: 0
这样就完成了字段添加。
5. 小结
生产环境MySQL添加或修改字段主要通过如下三种方式进行,实际使用中还有很多注意事项,大家要多多总结。
直接添加
如果该表读写不频繁,数据量较小(通常1G以内或百万以内),直接添加即可(可以了解一下online ddl的知识)
使用pt_osc添加
如果表较大 但是读写不是太大,且想尽量不影响原表的读写,可以用percona tools进行添加,相当于新建一张添加了字段的新表,再降原表的数据复制到新表中,复制历史数据期间的数据也会同步至新表,最后删除原表,将新表重命名为原表表名,实现字段添加
先在从库添加 再进行主从切换
如果一张表数据量大且是热表(读写特别频繁),则可以考虑先在从库添加,再进行主从切换,切换后再将其他几个节点上添加字段
mysql大表不停机加字段_mysql大表在不停机的情况下增加字段该怎么处理相关推荐
- MySQL 分页优化中的 “ INNER JOIN方式优化分页算法 ” 到底在什么情况下会生效?...
最近无意间看到一个 MySQL 分页优化的测试案例,并没有非常具体地说明测试场景的情况下,给出了一种经典的方案.因为现实中很多情况都不是固定不变的,能总结出来通用性的做法或者说是规律,是要考虑非常多的 ...
- MySQL 分页优化中的 “ INNER JOIN方式优化分页算法 ” 到底在什么情况下会生效?
最近无意间看到一个 MySQL 分页优化的测试案例,并没有非常具体地说明测试场景的情况下,给出了一种经典的方案.因为现实中很多情况都不是固定不变的,能总结出来通用性的做法或者说是规律,是要考虑非常多的 ...
- mysql 为数据表添加字段_MySQL数据表添加字段实例
MySQL 允许在开头.中间和结尾处添加字段.针对不同的位置,MySQL数据表添加字段的方式也有所不同,下面我们一起来看MySQL数据表添加字段的实例,方便我们理解MySQL数据表添加字段的方式. M ...
- mysql修改表结构 删除字段_mysql更改表结构:添加、删除、修改字段、调整字段顺序...
添加字段: alter table `user_movement_log` Add column GatewayId int not null default 0 AFTER `Regionid` ( ...
- mysql增加表字段_MySql新增表的字段,删除表字段
1增加两个字段: create table id_name(id int,name varchar(20));//创建原始数据表 alter table id_name add age int,add ...
- mysql带where的join加索引_MySQL索引分析和优化+JOIN的分类(转)
join : 左右合併 inner join : 只顥示符合修件的資料列 (左右互相比對) left join : 顥示符合條件的右資料列及左邊不符合條件的資料列 (此時右邊的資料會以 NULL 顯示 ...
- mysql 一对多 右表多条记录合并_MYSQL 单表一对多查询,将多条记录合并成一条记录...
一.描述: 在MySQL 5.6环境下,应工作需求:将一个表中多条某个相同字段的其他字段合并(不太会表达,有点绕,直接上图) 想要达到的效果: 实现SQL语句: SELECT a.books, GRO ...
- mysql创建表时设置外键_mysql创建表时设置外键约束的方法
mysql创建表时设置外键约束的方法 发布时间:2020-06-17 15:54:11 来源:亿速云 阅读:312 作者:元一 MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中, ...
- mysql的innodb表生成的物理文件_MySQL innodb表使用表空间物理文件复制或迁移表
MySQL InnoDB引擎的表通过拷贝物理文件来进行单表或指定表的复制,可以想到多种方式,今天测试其中2种: 将innodb引擎的表修改为Myisam引擎,然后拷贝物理文件 直接拷贝innodb的表 ...
最新文章
- Google Pixel 超分辨率--Super Resolution Zoom
- 美国 AI 博士:什么都不会怎么学 Python?
- 2019年十大AI创业死亡名单:无人车机器人为主,B轮阵亡最多
- python pandas空值与缺失值处理
- 【两分钟带你了解树】数据结构04-树结构的概述
- Nginx 学习笔记(五)nginx-vod-module 模块
- SAP Cloud for Customer 标准培训课程
- 忽略Java中的自签名证书
- JavaScript DOM编程艺术第二版学习(1/4)
- (STL,map,queue)团体队列
- LeetCode 476. Number Complement
- 人工智能 - paddlepaddle飞桨 - 入门之安装教程
- get post put delete在vue中传参方式
- java导出文件教程_Java文件教程
- (python3) 字符串压缩与解压
- xp系统wep服务器,iis 6.0 完整安装包 适用xp
- 统计通话次数和时间的软件_通话时间统计
- libiec61850 1.5.1 新版本
- canvas-八卦图和时钟实现
- spring项目启动慢问题
热门文章
- 如何将excel文件转换成csv文件并读取
- 面对“烟囱式”难题,联想企业网盘展现跨时空延展能力
- 北京市某超算数据中心的空调设计
- qt5.15.2在银河麒麟v10sp1上编译源码后安装运行
- 获取,设置HTML控件位置
- 技术管理三板斧第一板斧拿结果-追过程
- Python3-word文档操作(一):利用python创建word文档,并且设置标题和正文的内容,设置字体样式
- 关于#matlab#的问题:出错 IF_Distributed_Kalman_difSNR_Fig3_4 (第 202 行) labelEst(itn,:) = double(idx==trust)
- 【Web前端HTML5CSS3】01-前端简介
- Windows安装PDMan及简单介绍