MySQL 更改 varchar 列长度需注意的事

文章探讨了MySQL5.7及以上版本中,特别是5.6引入的INPLACE和COPY算法在ALTERTABLE时处理VARCHAR字段长度更改的限制。INPLACE不支持长度从小于256字节增至大于等于256字节的情况,需用COPY。文章提供了详细的解释和注意事项。
摘要由CSDN通过智能技术生成

由于个人能力有限,文中可能存在错误,并且很多细节没有深入分析,欢迎批评指正。

问题现象

MySQL 5.7 版本中,在对表字段 varchar 长度进行更改时出现报错,如下所示:

mysql> ALTER TABLE t1 MODIFY COLUMN C1 varchar(100) NOT NULL,ALGORITHM=INPLACE, LOCK=NONE;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

根据报错提示,本次字段长度更改并不支持 INPLACE 算法,需通过 COPY 的方式执行。

关于 MySQL DDL 算法:
1)COPY ,MySQL 5.5 及以下版本默认算法。
2)INPLACE ,MySQL 5.6开始被引入并默认使用,包含 rebuild-table 和 not-rebuild-table 两种类型,两者的主要差异在于是否需要重建源表。其次,该算法支持在 DDL 过程中间的读写,但是对写入的数据量有上限,不能超过 innodb_online_alter_log_max_size(默认为 128M)。
3)INSTANT ,MySQL 8.0.12 开始被引入并默认使用,支持快速加列,更多信息请自行查询官方手册。

表结构信息:

CREATE TABLE `t1` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `c1` varchar(10) NOT NULL,
  `c2` varchar(20) NOT NULL,
  `c3` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_c123` (`c1`,`c2`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4 

此外,该问题在 MySQL 8.0 版本中也存在。

原因分析

该 DDL 操作计划是将字段 c1 数据类型长度从 varchar(10) 扩展为 varchar(100),这意味着该字段所能容纳的字符数上限将由原先的 10 个字符提升至 100 个字符。

在 MySQL 中,字段长度的存储单位是字节,而非字符。考虑到每个字节由 8 位(bits)构成,因此单个字节能够表示的最大数值是 2^8 - 1,即 255。这是因为二进制计数从 0 开始,所以 8 位二进制数的范围是从 00000000 到 11111111 ,转换为十进制后的最大值为 255。

在本次操作中,由于字符集采用的是 utf8mb4,每个字符占用的字节数为 4。因此,当 c1 字段的长度从 varchar(10) 变为 varchar(100) 时,所需的存储空间从原先的 40 字节(10个字符 x 4字节/字符)增加到了 400 字节(100个字符 x 4字节/字符)。这意味着存储该字段长度的元数据需要两个字节来表示。

在这种情况下,如果 SQL 语句中指定使用 INPLACE 算法来执行这一操作,则会报错,因为INPLACE 算法通常不支持这种需要增加存储空间的修改操作。此时,需要通过 COPY 算法来执行这一 DDL 操作,具体而言,就是创建一个新的表结构,将旧表的数据复制到新表中,然后替换旧表。这一过程确保了数据的完整性和一致性,同时适应了字段长度变更所带来的新的存储需求。

更多信息也可参考官方手册说明:

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.
Note
The byte length of a VARCHAR column is dependant on the byte length of the character set.

注意总结

总结关于 varchar 列长度更改的限制如下:

  1. 长度变化在 0 到 255 字节的之间:这种更改可以通过 INPALCE 进行,此时长度字节的数量(1个)保持不变。
  2. 长度从 256 字节或更多增至更大:此类更改同样支持 INPALCE 进行,因为长度字节的数量(2个)也维持不变。
  3. 长度从小于 256 字节增至 256 字节或更多:这种更改不能通过 INPALCE 进行,因为长度字节的数量会从 1 个增加到 2 个。此类更改需要复制整个表(使用 ALGORITHM=COPY),以容纳新增的长度字节。
  4. 长度减少的更改:减少varchar列的长度同样不支持 INPALCE 操作。

在进行 varchar 列长度更改时,务必注意上述限制,以避免因锁表而对业务产生不良影响。同时,在尝试执行指定的原地算法时,需准备好应对可能出现的报错,并采取相应的排查措施。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值