每日一面 - MySQL 大表添加一列

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 每日一面 - MySQL 大表添加一列
问题参考自: https://www.zhihu.com/question/440231149 ,mysql中,一张表里有3亿数据,未分表,要求是在这个大表里添加一列数据。数据库不能停,并且还有增删改操作。请问如何操作?答案为个人原创

以前老版本 MySQL 添加一列的方式:

ALTER TABLE 你的表 ADD COLUMN 新列 char(128);

会造成锁表,简易过程如下:

  1. 新建一个和 Table1 完全同构的 Table2
  2. 对表 Table1 加写锁
  3. 在表 Table2 上执行 ALTER TABLE 你的表 ADD COLUMN 新列 char(128)
  4. 将 Table1 中的数据拷贝到 Table2
  5. 将 Table2 重命名为 Table1 并移除 Table1,释放所有相关的锁

如果数据量特别特别大,那么锁表时间很长,期间所有表更新都会阻塞,线上业务不能正常执行。

针对 MySQL 5.6(不包含)之前的版本,通过触发器将一个表的更新在另一个表上重复,并进行数据同步,当数据同步完成时,业务上修改表名为新表并发布。业务不会暂停。触发器设置类似于:

create trigger person_trigger_update AFTER UPDATE on 原有表 for each row 
begin set @x = "trigger UPDATE";
Replace into 新表 SELECT * from 原有表 where 新表.id = 原有表.id;
END IF;
end;

MySQL 5.6(包含) 以后的版本引入了在线 DDL 的功能:

Alter table 你的表 , ALGORITHM [=] {DEFAULT|INSTANT|INPLACE|COPY}, LOCK [=] { DEFAULT| NONE| SHARED| EXCLUSIVE }

其中的参数:

  • ALGORITHM:
  • DEFAULT:默认方式,在 MySQL 8.0中,如果未显示指定 ALGORITHM,那么会优先选择 INSTANT 算法,如果不行再使用 INPLACE 算法,如果不支持 INPLACE 算法则使用 COPY 的方式完成
  • INSTANT:8.0 中新添加的算法,添加列是立即返回。但是不能是虚拟列。这个原理很简单,对于新建一列,表所有原有数据并不是立刻发生变化,只是在表字典里面记录下这个列和默认值,对于默认的 Dynamic 行格式(其实就是 Compressed 的变种),如果更新了这一列则原有数据标记为删除在末尾追加更新后的记录。这样做就是没有提前预留出列空间,之后更新可能经常会发生行记录空间变动。但是对于大多数业务,都是最近的时间的记录才会修改,所以问题不大。
  • INPLACE:在原表上直接进行修改,不会拷贝临时表,可以逐条记录修改,不会产生大量的 undolog 以及 redolog,不会占用很多 buffer。可以避免重建表带来的IO和CPU消耗,保证期间依然良好的性能和并发。
  • COPY:拷贝到临时新表上进行修改。由于记录拷贝,会产生大量的 undolog 以及 redolog,并占用很多 buffer,对业务性能有影响。


  • LOCK:
  • DEFAULT:和 ALGORITHM 的 DEFAULT 类似
  • NONE:无锁,允许并发读取和更新表
  • SHARED:共享锁,允许读取不允许更新
  • EXCLUSIVE:不允许读取和更新


各个版本支持的在线 DDL 修改使用的算法的对比:


微信图片_20220624204436.jpg


参考文档:

可以通过:

ALTER TABLE 你的表 ADD COLUMN 新列 char(128), ALGORITHM=INSTANT, LOCK=NONE;

类似的语句,实现在线增加字段。最好还是明确 ALGORITHM 以及 LOCK,这样执行 DDL 的时候能明确知道到底会对线上业务有多大影响

同时,执行在线 DDL 的过程大概是:


微信图片_20220624204505.jpg


图片参考自:https://zhuanlan.zhihu.com/p/162073721

可以看出,在开始阶段需要 metadata lock,metadata lock 是在 5.5 才引入到mysql,之前也有类似保护元数据的机制,只是没有明确提出 metadata lock 概念而已。但是 5.5 之前版本(比如5.1)与5.5之后版本在保护元数据这块有一个显著的不同点是,5.1对于元数据的保护是语句级别的,5.5对于metadata的保护是事务级别的。所谓语句级别,即语句执行完成后,无论事务是否提交或回滚,其表结构可以被其他会话更新;而事务级别则是在事务结束后才释放 metadata lock。

引入 metadata lock 后,主要解决了2个问题,一个是事务隔离问题,比如在可重复隔离级别下,会话A在2次查询期间,会话B对表结构做了修改,两次查询结果就会不一致,无法满足可重复读的要求;另外一个是数据复制的问题,比如会话A执行了多条更新语句期间,另外一个会话B做了表结构变更并且先提交,就会导致 slave 在重做时,先重做 alter,再重做 update 时就会出现复制错误的现象。

如果当前有很多事务在执行,并且有那种包含大查询的事务,例如:

START TRANSACTION;
select count(*) from 你的表
。。。。

这样类似的会执行较长时间的事务,也会阻塞。

所以,原则上:

  • 避免大事务
  • 在业务低峰去做表结构变化


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11月前
|
存储 SQL JavaScript
阿里一面:MySQL 单表数据最大不要超过多少行?为什么?
阿里一面:MySQL 单表数据最大不要超过多少行?为什么?
|
1月前
|
缓存 关系型数据库 MySQL
史上最全MySQL 大表优化方案(长文)
史上最全MySQL 大表优化方案(长文)
441 0
|
11月前
|
SQL 关系型数据库 MySQL
MySQL-在线处理大表数据 & 在线修改大表的表结构
MySQL-在线处理大表数据 & 在线修改大表的表结构
177 0
|
6月前
|
SQL 关系型数据库 MySQL
MySQL 大表如何优化查询效率?
MySQL 大表如何优化查询效率?
78 0
|
8月前
|
数据库连接
MySQL-小表驱动大表
MySQL-小表驱动大表
77 0
|
8月前
|
存储 运维 容灾
使用NineData实现亿级别MySQL大表迁移
NineData提供了高效、稳定的MySQL大表迁移能力,解决了传统迁移方案的问题。通过智能分片、行级并发和动态攒批等核心技术,NineData保证了迁移性能。同时,NineData具备完善的容灾能力,提高了大表迁移的成功率。通过数据和结构的对比功能,保障了数据的一致性。使用NineData进行迁移任务的配置简单快捷,只需一分钟即可完成。NineData还提供了丰富的检查项和观测、干预能力,帮助用户追踪迁移进展并处理异常情况。
763 0
使用NineData实现亿级别MySQL大表迁移
|
9月前
|
存储 算法 关系型数据库
mysql中锁机制和大表优化问题
mysql中锁机制和大表优化问题
|
9月前
|
存储 SQL 运维
PolarDB MySQL大表实践-分区表篇
背景:分区表到底是什么?分区作为传统企业级数据库的特性,早已经在很多大数据和数仓场景中得到广泛应用。基于维基百科的解释,分区是将逻辑数据库或其组成元素如表、表空间等划分为不同的独立部分。数据库分区通常是出于可管理性、性能或可用性的原因,或者是为了负载平衡。它在分布式数据库管理系统中很流行,其中每个分区可能分布在多个节点上,节点上的用户在分区上执行本地事务。这提高了具有涉及某些数据视图的常规事务的站
334 0
PolarDB MySQL大表实践-分区表篇
|
11月前
|
存储 SQL 关系型数据库
阿里一面:MySQL 单表数据最大不要超过多少行?为什么?这样回答满分!
阿里一面:MySQL 单表数据最大不要超过多少行?为什么?这样回答满分!
|
11月前
|
SQL 存储 缓存
MySQL-性能优化_大表和大事务的常用处理方案
MySQL-性能优化_大表和大事务的常用处理方案
101 0
MySQL-性能优化_大表和大事务的常用处理方案