首页 > 数据库 >MySQL在线修改varchar列的注意事项和方法

MySQL在线修改varchar列的注意事项和方法

时间:2023-08-03 11:34:41浏览次数:37  
标签:abc varchar mysql address 注意事项 MySQL table NULL


在数据库管理中,alter table操作是修改数据库结构的关键部分。mysql从5.6版开始提供在线操作,提供了一种在不锁定表的情况下执行这些更改的便捷方法。不过,这也有一些注意事项。在本文中,将探讨在线修改varchar列的过程,深入了解在扩大此类列的大小时获得的启发。

假设有以下表定义,该表要求扩展名为"address"的varchar列以容纳更多数据。下面是原始表定义:

drop table if exists abc_address;
create table abc_address (id int not null auto_increment primary key,abc_address varchar(50) not null) engine=innodb default charset=utf8mb3;

执行以下alter table操作:

mysql> alter table abce.abc_address change column abc_address abc_address varchar(85) not null default '', algorithm=inplace, lock=none;
query ok, 0 rows affected (0.01 sec)
records: 0  duplicates: 0  warnings: 0

mysql> show create table abc_address\G
*************************** 1. row ***************************
       Table: abc_address
Create Table: CREATE TABLE `abc_address` (
  `id` int NOT NULL AUTO_INCREMENT,
  `abc_address` varchar(85) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
1 row in set (0.00 sec)

修改似乎成功了,我们看到表定义也相应地被修改了。

现在,尝试后续更改--尝试扩展到100。令人惊讶的是,当我们尝试将varchar列长度增加到100时,却遇到了错误:

mysql> alter table abce.abc_address change column abc_address abc_address varchar(100) not null default '', algorithm=inplace, lock=none;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

DDL被拒绝,MySQL建议改用COPY算法。将DDL改成copy算法,施加共享锁,然后执行成功。如:
命令改为使用算法复制和共享锁,如下所示,成功执行了 ALTER VARCHAR 列:

mysql> alter table abce.abc_address change column abc_address abc_address varchar(100) not null default '', algorithm=copy, lock=shared;
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> show create table abc_address\G
*************************** 1. row ***************************
Table: abc_address
Create Table: CREATE TABLE `abc_address` (
`id` int NOT NULL AUTO_INCREMENT,
`abc_address` varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
1 row in set (0.00 sec)

 

in-place执行alter的限制
虽然最初允许将varchar列长度增加到85,但为什么mysql拒绝在线修改(algorithm=inplace)将varchar列长度修改为100呢?

可以从文档中找到答案,这与varchar如何存储数据(实际上是前缀和数据)有关。在mysql中,varchar值以一个或两个字节长度的前缀(记录字符串的长度)加数据的方式存储。
前缀长度取决于数据的大小。数据长度不超过255字节时,只使用一个字节的前缀,但数值超过255字节时,需要两个字节的前缀长度。因此,in-place的alter table只支持将varchar列的大小从0增加到255字节,或从256字节增加到更大。
当alter需要扩展前缀长度时,它不允许in-place修改。

要查看实际操作,可以查询information_schema.columns表。最初,当列长度被alter为85时,请注意以下细节。

mysql> select * from information_schema.columns where table_schema = 'abce' and table_name in ('abc_address') and column_name = 'abc_address'\G
*************************** 1. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: abce
TABLE_NAME: abc_address
COLUMN_NAME: abc_address
ORDINAL_POSITION: 2
COLUMN_DEFAULT:
IS_NULLABLE: NO
DATA_TYPE: varchar
CHARACTER_MAXIMUM_LENGTH: 85
CHARACTER_OCTET_LENGTH: 255
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
DATETIME_PRECISION: NULL
CHARACTER_SET_NAME: utf8mb3
COLLATION_NAME: utf8mb3_general_ci
COLUMN_TYPE: varchar(85)
COLUMN_KEY:
EXTRA:
PRIVILEGES: select,insert,update,references
COLUMN_COMMENT:
GENERATION_EXPRESSION:
SRS_ID: NULL
1 row in set (0.00 sec)

在这里,character_maximum_length指定了存储在列中的字符长度,
而character_octet_length则指定了以字节为单位的长度。需要注意的是,该列的字节长度已经是255,再增加就需要mysql将varchar前缀大小扩展到两个字节。将varchar列大小改为100后,存储需求如下。

mysql> select * from information_schema.columns where table_schema = 'abce' and table_name in ('abc_address') and column_name = 'abc_address'\G
*************************** 1. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: abce
TABLE_NAME: abc_address
COLUMN_NAME: abc_address
ORDINAL_POSITION: 2
COLUMN_DEFAULT:
IS_NULLABLE: NO
DATA_TYPE: varchar
CHARACTER_MAXIMUM_LENGTH: 100
CHARACTER_OCTET_LENGTH: 300
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
DATETIME_PRECISION: NULL
CHARACTER_SET_NAME: utf8mb3
COLLATION_NAME: utf8mb3_general_ci
COLUMN_TYPE: varchar(100)
COLUMN_KEY:
EXTRA:
PRIVILEGES: select,insert,update,references
COLUMN_COMMENT:
GENERATION_EXPRESSION:
SRS_ID: NULL
1 row in set (0.00 sec)

 

在这种情况下如何在线修改varchar列?

在mysql中,面对在线alter table遇到varchar列的限制时,可以考虑使用percona工具包的pt-online-schema-change。它是众所周知的行业标准工具,也是percona工具包的一部分,能以最少的停机时间执行在线更改。

 

alter table修改varchar列的character set
字符集定义了存储要求,更改character set也会导致所需字节数增加。因此,在更改时也需要考虑这一点。查看下面的示例,可以看到要存储85字节的varchar长度,长度已从之前的255字节增加到340字节。

mysql> alter table abce.abc_address change column abc_address abc_address varchar(85) charset utf8mb4 not null default '', algorithm=inplace, lock=none;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
mysql> alter table abce.abc_address change column abc_address abc_address varchar(85) charset utf8mb4 not null default '', algorithm=copy, lock=shared;
Query OK, 0 rows affected (0.02 sec)
Records: 0 Duplicates: 0 Warnings: 0

mysql> select * from information_schema.columns where table_schema = 'abce' and table_name in ('abc_address') and column_name = 'abc_address'\G
*************************** 1. row ***************************
TABLE_CATALOG: def
TABLE_SCHEMA: abce
TABLE_NAME: abc_address
COLUMN_NAME: abc_address
ORDINAL_POSITION: 2
COLUMN_DEFAULT:
IS_NULLABLE: NO
DATA_TYPE: varchar
CHARACTER_MAXIMUM_LENGTH: 85
CHARACTER_OCTET_LENGTH: 340
NUMERIC_PRECISION: NULL
NUMERIC_SCALE: NULL
DATETIME_PRECISION: NULL
CHARACTER_SET_NAME: utf8mb4
COLLATION_NAME: utf8mb4_0900_ai_ci
COLUMN_TYPE: varchar(85)
COLUMN_KEY:
EXTRA:
PRIVILEGES: select,insert,update,references
COLUMN_COMMENT:
GENERATION_EXPRESSION:
SRS_ID: NULL
1 row in set (0.00 sec)

 

最后
mysql中的在线alter table操作为数据库管理带来了灵活性,但它们也有特定的局限性,尤其是在处理varchar列时。
了解底层存储机制对成功更改至关重要。copy算法可以帮助管理超出255字节限制的varchar扩展,但pt-online-schema-change更易于使用,且在执行操作时减少了出错。

标签:abc,varchar,mysql,address,注意事项,MySQL,table,NULL
From: https://www.cnblogs.com/abclife/p/17600321.html

相关文章

  • MySQL 锁机制存在的价值是什么?
    MySQL中的锁机制对于确保数据库的一致性、并发控制和事务完整性非常关键。以下是MySQL锁机制存在的主要价值:并发控制:在多用户并发访问数据库时,锁可以确保在同一时间只有一个事务能够访问同一数据,防止数据混乱和不一致。数据完整性:通过锁机制,MySQL可以确保在事务处理过程中的数据......
  • MySQL生成UUID
    1uuid函数在MySQL中,可以用uuid()函数来生成一个UUID,如下:selectuuid()asuuid;2replace函数默认生成的uuid含有'-',我们可以使用replace函数替换掉'-',SQL如下:selectreplace(uuid(),'-','');3insert语句中使用uuid如果一个表中id字段使用uuid来作为主键,那我们可以......
  • MySQL常用命令
    建库CREATEDATABASE`databaseName`DEFAULTCHARACTERSETutf8COLLATEutf8_general_ci;创建用户CREATEUSER'userName'@'localhost'IDENTIFIEDBY'eKw5Ap9EBwjIRc_AO2!Y84';--userName:你将创建用户的名字--localhost:本地用户,如果想让该用户可以**从任意......
  • 运维——Centos7 安装MySQL详细步骤
    转自:https://blog.csdn.net/javaluckyfish/article/details/1314210161.卸载MariaDB在CentOS中默认安装有MariaDB,是MySQL的一个分支,主要由开源社区维护。CentOS7及以上版本已经不再使用MySQL数据库,而是使用MariaDB数据库。如果直接安装MySQL,会和MariaDB的文件冲突。因此,需要先卸......
  • 模型:Django与Mysql交互
     1、创建数据库用户前提是已经在本机或者服务器上安装了mysql。createdatabaseslw;createuser'slw'@'%'identifiedby'pwd'grantallprivilegesonslw.*to'slw'@'%'identifiedby'pwd'withgrantoption;flushprivile......
  • MySQL提权之启动项提权——开机启动的程序,那时候启动的程序权限都是system
    关于MySQL的启动项提权,听其名知其意。就是将一段VBS脚本导入到 C:\DocumentsandSettings\AllUsers\「开始」菜单\程序\启动下,如果管理员重启了服务器,那么就会自动调用该脚本,并执行其中的用户添加及提权命令!这里有两种思路:1.如果 C:\DocumentsandSettings\AllUsers\「......
  • 数据库事务的四种隔离性及Oracle\MySQL默认隔离级别和原因分析
    1事务一个事务中的一系列的处理操作要么全部成功,要么一个都不做。在数据库操作中,一项事务(Transaction)是由一条或多条操作数据库的SQL语句组成的一个不可分割的工作单元。事务的处理结果有两种:1)当事务中的所有步骤全部成功执行时,事务提交,成功;2)如果其中任何一个步骤失败,该事务......
  • 关于scrapy爬虫的注意事项
    1.图片下载的设置classClawernameSpider(scrapy.Spider):#定制化设置custom_settings={'LOG_LEVEL':'DEBUG',#Log等级,默认是最低级别debug'ROBOTSTXT_OBEY':False,#defaultObeyrobots.txtrules'DOWNLO......
  • 数据库(MySQL语句)
    一.概念数据库是长期存放在计算机内、有组织的、可共享的数据集合数据库中的数据按一定的数据模型组织、描述和存储,且具有较小的冗余度、较高的数据独立性和易拓展性数据库管理系统(DBMS)是用于建立、使用和维护数据库的软件建立:定义、组织和存储数据使用:查询、插入、删除和......
  • 软件测试 | Windows平台下配置MySQL
    对于noinstall方式安装的MySQL,系统的参数配置、服务的启动关闭都需要手工在命令窗口中进行设置。参数文件可以在多个位置进行设置,这里用一个c:\my.cnf来进行操作,其他更详细的参数位置可以参考第24章中的参数设置方法。对于初学者来说,my.cnf并不知道该怎样配置。MySQL为用......