前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OnLine DDL -- 扩展 VARCHAR 列大小

OnLine DDL -- 扩展 VARCHAR 列大小

作者头像
保持热爱奔赴山海
发布2022-01-11 13:23:03
3630
发布2022-01-11 13:23:03
举报
文章被收录于专栏:数据库相关

更详尽的见官方文档: ​​https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html​

同事前几天提了句varchar 255以下的扩大列宽度是不锁表的,再往上扩就是需要加锁的。想起来好像是有这个说法,查了下官方文档确实如此,顺手试验下看看,于是有了下文。

官方文档翻译:

原则:VARCHAR 列所需的长度字节数必须保持不变。对于大小为 0 到 255 个字节的 VARCHAR 列,需要一个长度字节来对值进行编码。对于大小为 256 字节或更多的 VARCHAR 列,需要两个长度字节。

因此,IN-PLACE ALTER TABLE 仅支持将 VARCHAR 列大小从 0 增加到 255 字节,或从 256 字节增加到更大的大小。

IN-PLACE ALTER TABLE 不支持将 VARCHAR 列的大小从小于 256 字节增加到等于或大于 256 字节的大小。在这种情况下,所需的长度字节数从 1 变为 2,例如从varchar(255)改为varchar(256)这种情况下就得使用 ALGORITHM=COPY。

注意: VARCHAR 列的字节长度取决于字符集的字节长度(也就是说latin1和utf8和utf8mb4是有区别的)。

看下我们最常见的UTF8字符集的情况:

代码语言:javascript
复制
CREATE TABLE `tb1` (
  `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `b` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

上面的表结构中,b列是定义为utf8,占3位,也就是我们要做到无锁扩展,最大只能到 255/3 约等于85 这个宽度。


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb1 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb1 CHANGE COLUMN b b VARCHAR(85), ALGORITHM=INPLACE, LOCK=NONE;


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb1 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb1 CHANGE COLUMN b b VARCHAR(86), ALGORITHM=INPLACE, LOCK=NONE;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

再看看utf8mb4字符集的varchar扩展长度的情况:

代码语言:javascript
复制
CREATE TABLE `tb5` (
  `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `b` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

上面的表结构中,b列是定义为 utf8mb4 ,占4位,也就是我们要做到无锁扩展,最大只能到 255/4 约等于 63 这个宽度。


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb5 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb5 CHANGE COLUMN b b VARCHAR(40), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb5 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb5 CHANGE COLUMN b b VARCHAR(63), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb5 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb5 CHANGE COLUMN b b VARCHAR(64), ALGORITHM=INPLACE, LOCK=NONE;  ---> 改为64这里报错了
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

再看看latin1字符集的varchar扩展长度的情况(255及以下):

代码语言:javascript
复制
CREATE TABLE `tb2` (
  `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `b` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- 重置下b列长度
MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(128), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(255), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(256), ALGORITHM=INPLACE, LOCK=NONE;  ---> 改为256这里报错了
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. 
Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

再看看latin1字符集的varchar扩展长度的情况(256往以上扩展):

代码语言:javascript
复制
CREATE TABLE `tb4` (
  `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `b` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(256);


MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(1024), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(256);

MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(4096), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

再看看latin1字符集的varchar扩展长度的情况(255以下往256扩展):

代码语言:javascript
复制
CREATE TABLE `tb3` (
  `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `b` varchar(252) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb3 CHANGE COLUMN b b VARCHAR(252);

MySQL [test]> ALTER TABLE tb3 CHANGE COLUMN b b VARCHAR(255), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb3 CHANGE COLUMN b b VARCHAR(252);

MySQL [test]> ALTER TABLE tb3 CHANGE COLUMN b b VARCHAR(256), ALGORITHM=INPLACE, LOCK=NONE;  ---> 改为256这里报错了
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. 
Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

再看看latin1字符集的varchar扩展长度的情况(255及以下的扩展):

代码语言:javascript
复制
CREATE TABLE `tb2` (
  `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `b` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(128), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(255), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(10);

MySQL [test]> ALTER TABLE tb2 CHANGE COLUMN b b VARCHAR(256), ALGORITHM=INPLACE, LOCK=NONE;  ---> 改为256这里报错了
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. 
Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

再看看latin1字符集的varchar扩展长度的情况(256往以上扩展):

代码语言:javascript
复制
CREATE TABLE `tb4` (
  `a` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `b` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(256);


MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(1024), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.00 sec)
Records: 0  Duplicates: 0  Warnings: 0


-- 重置下b列长度
MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(256);

MySQL [test]> ALTER TABLE tb4 CHANGE COLUMN b b VARCHAR(4096), ALGORITHM=INPLACE, LOCK=NONE;
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

其它:

  1. 不支持使用INPLACE方式 ALTER TABLE 减小 VARCHAR 大小。减小 VARCHAR大小必须使用ALGORITHM=COPY

下面的几个操作也是不锁的,

ALTER TABLE tbl CHANGE old_col_name new_col_name data_type, ALGORITHM=INPLACE, LOCK=NONE;

​ALTER TABLE tbl_name DROP COLUMN column_name, ALGORITHM=INPLACE, LOCK=NONE;

​ALTER TABLE table AUTO_INCREMENT=next_value, ALGORITHM=INPLACE, LOCK=NONE;

​ALTER TABLE t1 DROP COLUMN c2, ALGORITHM=INPLACE, LOCK=NONE;

这里没有一一罗列,具体以官方文档为准。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/12/09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档