作者:胡存存

爱可生 DBA 团队成员,主要负责 MySQL 故障处理和 SQL 审核优化。对技术执着,为客户负责。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


MySQL 在 5.6 引入 Online DDL 之后,在 5.7 和 8.0 版本又对这一功能进行了大幅的优化。尤其是在 8.0 之后,已经实现了列的秒加。在 5.7 中有些 DDL 操作也实现了秒修改,比如修改字段的默认值,修改列名,但是这些在工作中不是很常见,今天我们讨论下能够实现秒修改的一种特殊情况,稍不注意可能就掉进坑中。

在日常工作中,我们用的最多的数据类型就是 int(bigint) 类型和 varchar 类型。在这两个数据类型中,其中 int 类型只要不超过数据类型允许的最大值,int(N) 类型的中的 N 不会影响输入的字节数,但是 varchar(N) 数据类型中的 N,当输入的字符数超过 N 时,就不允许输入,这时就需要扩容,这也是我们经常会遇到的一种数据变更。当出现这种需求,我们是采用 MySQL 的 Online DDL 直接修改还是用第三方的工具呢。我们先看下官网关于扩 varchar 类型的描述:

参考文章:https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html

通过上图可以发现,Extending VARCHAR column size 在 In Place 是 yes,Rebuilds Table 是 no,也就是在修改是在修改时不用 copy 表,那是不是这样,我们验证下。我们用 sysbench 准备 4 张表,单表 500w,用 4 线程压数据库,模拟业务量(数据库版本:5.7.29)。表结构为:

root@localhost[sbtest]> show create table sbtest1\G*************************** 1. row ***************************       Table: sbtest1Create Table: CREATE TABLE `sbtest1` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `k` int(11) NOT NULL DEFAULT '0',  `c` char(120) NOT NULL DEFAULT '',  `pad` char(60) NOT NULL DEFAULT '',  `c1` varchar(10) NOT NULL DEFAULT 'cc',  PRIMARY KEY (`id`),  KEY `k_1` (`k`)) ENGINE=InnoDB AUTO_INCREMENT=5000001 DEFAULT CHARSET=utf8mb41 row in set (0.00 sec)

此时启动 sysbench,看到此时的 qps 在 5000 左右,

此时将 c1 列从 varchar(10) 扩到 varchar(50),我们发现秒修改,直接毫无感知,与官网上说的一样。

这时候字节长度又不够了,我们需要扩到 100,这时候,我们发现了异常,这次不再是秒修改,而是停在了那,现在是不是觉得有点不妙,这时候,再看我们的压测日志,

这时候业务完全被阻塞了,这时候,脑瓜子是不是嗡嗡的了。。。

到底怎么回事,我们看下官网怎么说:Extending VARCHAR column sizeALTER TABLE tbl_name CHANGE COLUMN c1 c1 VARCHAR(255), ALGORITHM=INPLACE, LOCK=NONE;The number of length bytes required by a VARCHAR column must remain the same. For VARCHAR columns of 0 to 255 bytes in size, one length byte is required to encode the value. For VARCHAR columns of 256 bytes in size or more, two length bytes are required. As a result, in-place ALTER TABLE only supports increasing VARCHAR column size from 0 to 255 bytes, or from 256 bytes to a greater size. In-place ALTER TABLE does not support increasing the size of a VARCHAR column from less than 256 bytes to a size equal to or greater than 256 bytes. In this case, the number of required length bytes changes from 1 to 2, which is only supported by a table copy (ALGORITHM=COPY). For example, attempting to change VARCHAR column size for a single byte character set from VARCHAR(255) to VARCHAR(256) using in-place ALTER TABLE returns this error:ALTER TABLE tbl_name ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(256);ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.由上文可知,在 varchar 类型中,当大小在 0 到 255 字节时,需要 1 个字节编码,当大于 255 时,需要 2 个字节编码。所以在相同字节编码的长度内变更,可以用 inplace 的方式,当字节编码长度变更时,只能用 copy 模式,这种情况下会完全阻塞表的读写。这样我们大约明白怎么回事了,但细想,又在哪里有问题,刚才我们在变更时,从 varchar(50) 到 varchar(100),还没到 255,为什么会出现 copy 表的现象?其实这里我们注意的是 varchar(N) 中,N 表示的是字符,而不是字节。所以,所以根据字符集不一样,每个字符需要的字节也不一样,所以在扩 varchar 长度时,N 的范围也不一样。在 utf8 字符集中,一个字符需要三个字节,所以,当 N<=85 时,需要一个 1 个字节编码,当 N>85 时,需要两个。所以我们来验证下,这里我们建 3 张表:

我们在表中插入几条数据,如下:

我们先修改 t1(字符集为 utf8)表,如下:

如上图,我们看到,当字段扩到 85 时,影响的行数还为 0,当扩到 86 之后,影响行数变为 3,也就是说字符长度从 85 扩到 86,此时发生了全表的 copy。当大于 86 之后,我们怎么扩,也不会发生表的 copy 操作了。我们再来验证 utf8mb4:

因为 utf8mb4 字符集一个字节需要 4 个字符,所以,当扩到 63 时,影响行数为 0,当扩到 64,影响行数为 3,发生了表的 copy。我们进一步用 latin1 验证,因为拉丁 1 字符集,一个字符只需要一个字节,所以,当扩大到 255 时,仍为 0,当扩大到 256 时,影响行数变为 2。

综上,我们可以总结:

  • 因为 varchar 字符集在存储时除了数据,还需要存 1~2 字节的前缀,长度前缀表示 varchar 中的字节数,当字段的字节数不大于 255 时,需要 1 个字节前缀,当大于 255 时,需要 2 个字节长度。

  • innodb 存储引擎,在扩大 varchar 字符长度时,当字节长度在 0~255 之间,或者 256 开始扩大,能用到 inplace 特性,当从 255 扩大到 256 时,只能 copy 表。

  • varchar(N) 字段类型中的 N 表示字符,根据不同字符集,单个字符需要的字节不一样,所以范围也不一样。

所以,我们在日常工作中,可以制定相应开发规范,尽量防止这类的事情发生。

另外,再提醒下,MySQL 5.7.20 之前的版本可能不支持(我测试的版本是 5.7.29),生产使用时需要再测试下。

此外,varchar 类型的缩小字符长度和字段数据类型更改都只能用 copy 的方式,有此需求要小心。


相关推荐:

技术分享 | Online DDL 工具 pt-osc

技术分享 | Online DDL 工具 gh-ost

新特性解读 | MySQL 8.0 之原子 DDL


社区近期动态

本文关键字:#DDL# #mysql5.7# 点一下“阅读原文”了解更多资讯

java有趣的技术分享ppt_技术分享 | 关于 MySQL Online DDL 有趣的验证相关推荐

  1. “大话架构”阿里架构师分享的Java程序员需要突破的技术要点

    一.源码分析 源码分析是一种临界知识,掌握了这种临界知识,能不变应万变,源码分析对于很多人来说很枯燥,生涩难懂. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心. 我认为是阅读源码的最核心 ...

  2. 阿里巴巴使用Java技术干嘛_阿里巴巴java技术岗三面分享

    阿里巴巴java技术岗三面分享 今天花时间整理了阿里巴巴Java岗技术三面的资料,分给大家做参考,祝大家都能找到好工作!加油! 一面 1.自我介绍,讲讲求职意向和擅长的技能 2.Tomcat的基本架构 ...

  3. 9月,水了几个大中厂前端面试的一些总结分享 | 掘金技术征文

    写在前面 工作吧,我觉得就像谈恋爱,不一定是找高富帅或者白富美,互相确认过眼神是对的人就可以~而面试的自信和对工资的要求,源于你过硬的基础和平时的思考.积累以及总结~ 8月底离职,其实是裸辞,当然大概 ...

  4. “我在小公司混,有没有资格去知名技术大会上做分享?”

    作者 | 王晔倞 责编 | 郭   芮 几个月前,我曾受邀参加过某场Flink与RocketMQ合办的技术沙龙,并跟现场小伙伴们围绕<ActiveMQ平滑迁移到RocketMQ挑战与实践> ...

  5. 2017 我所分享的技术文章总结(下)

    对下半年所分享的文章进行整理,上半年总结的 98 篇好文请点击这里,很多读者当时忘记了收藏,以致于查找一篇历史文章很费劲,因此在这里顺便做下记录.目前就分下下面几个大类,没有更多细分,已基本可以查找了 ...

  6. Whale 帷幄技术周大咖分享:AI 迎来大洗牌

    作为国际专业的全域数字化营销运营平台,Whale 帷幄极为关注人工智能 (AI), 大规模物联网络 (IoT) 和数据模型 (Data) 等关键技术创新. 为此,Whale 帷幄重视帮助员工在前沿技术 ...

  7. 一文看懂“声纹识别VPR” | AI产品经理需要了解的AI技术概念_团员分享_@cony

    前言:声纹识别是AI领域中一个看似很小.但其实有机会在近期落地,且比较有意思的细分方向:本文作者是"AI产品经理大本营"团员@cony  ,她总结了AI产品经理"最必要& ...

  8. AutoML前沿技术与实践经验分享 | 免费公开课

    传统机器学习的解决范式可表示为: ML Solution = ML expertise + Computation + Data 新机器学习范式可表示为: New ML Solution = 100x ...

  9. AutoML前沿技术与实践经验分享 | 免费报名

    传统机器学习的解决范式可表示为: ML Solution = ML expertise + Computation + Data 新机器学习范式可表示为: New ML Solution = 100x ...

最新文章

  1. qt linux mac,MacOS下Qt Installer Framework使用教程【个人经验】
  2. mysql的limit优化_mysql数据库limit优化例子(百万级数据)
  3. ajax请求php返回的数据是整个页面的html,Ajax出错并返回整个页面html的问题
  4. 大唐发电厂计算机考试题,全国计算机等级考试上机考试与题库解析:一级B
  5. redhat6.3的linux内核版本,1-6-RHEL6.3-内核升级(Red Hat Enterprise Linux Server6.3)@树袋飘零...
  6. python小波分解与重构_小波分解和重构
  7. 125_Power BI 中 DAX 的性能测试
  8. 3.9 训练一个 Softmax 分类器
  9. 10.PHP中的赋值运算符
  10. android源码分析网上随笔记录
  11. 笔记-微信订阅号开发
  12. python获取erp数据_python自学之路-数据读取
  13. 「运维有小邓」ADAudit Plus(AD域审计工具)的主要优势?
  14. 【转】最实用的IT类网站及工具大集合
  15. vue-js实现日期加减,年月日,及单位换算。
  16. PBR——概述、基于物理的材质
  17. 程序员适合做自由职业者吗?
  18. [PDF]我们经常使用的PDF是什么? PDF, PDF/A, PDF/Archive, OFD
  19. mul matlab,[转载]Matlab boxplot for Mul
  20. 数据中心产业怎样实现绿色环保?

热门文章

  1. 以 B2C 和 B2B 方式启动 SAP Spartacus 的批处理文件
  2. JavaScript 里 window, document, screen, body 这几个名词的区别
  3. SAP Spartacus全局配置模块里和layoutSlot相关的配置
  4. SAP Spartacus HTTP请求url里的语言和货币参数是如何加上去的
  5. 关于jasmine里debugElement.query和fixture.detectChanges的依赖关系
  6. 关于SAP S/4HANA里ABAP源代码管理功能的增强
  7. 将Spring Boot作为守护进程启动的一种简单的方法
  8. campaign read in WebUI - Fiori is correct!
  9. change all day checkbox in Fiori ui
  10. sap.ca.ui.utils.busydialog - scenario1 - opportunity opened