秒级加列

RDS MySQL的秒级加列功能通过变更元数据实现快速加列操作,避免全表数据重建,可在秒级内完成,且与表数据量大小无关。秒级加列几乎不消耗额外系统资源,也不会对业务造成锁表或阻塞的影响,适用于需要频繁扩展表结构且对业务连续性要求较高的场景。

功能说明

RDS MySQL的秒级加列(Instant Add Column)通过变更数据字典的元数据来优化ADD COLUMN 操作。该功能避免了传统DDL操作对全表数据的修改或重建,实现加列操作在秒级内完成,且不受表数据量影响。

秒级加列与传统加列的核心优势对比:

对比项

传统加列(CopyInplace模式)

RDS秒级加列(Instant模式)

加列耗时

需要全表数据重建,耗时与表大小成正比。

仅修改元数据,操作时长可控制在秒级。

资源消耗

临时占用大量系统资源(如IO、内存)。

几乎不消耗额外资源。

业务影响

长事务或高并发场景可能阻塞在线业务。

无锁表或阻塞影响。

表大小限制

无法支持大表快速加列。

支持任意大小表快速加列。

前提条件

实例版本要求如下,当小版本不符合要求时,可以升级内核小版本

  • MySQL 8.0:所有内核小版本均支持

  • MySQL 5.7:内核小版本大于等于20250331

使用限制

  • 引擎限制:仅支持InnoDB引擎。

  • 表类型限制:不支持压缩表、带全文索引的表和临时表。

  • 操作限制:不支持多操作合并,例如在添加列的同时添加索引。

  • 加列位置限制

    MySQL版本

    内核小版本

    加列位置

    5.7

    大于等于20250331

    默认最后一列。

    8.0

    低于20230630

    默认最后一列。

    大于等于20230630

    支持在新增列时指定列位置。

开启秒级加列

  1. 访问RDS实例列表,选择地域并单击目标实例ID。

  2. 在左侧导航栏,单击参数设置

  3. 可修改参数页签的loose_instant_ddl_enabled参数的运行参数值列,修改参数值为ON,完成后单击确定

  4. 单击提交参数,在弹出的对话框中,选择生效的时间段,完成后单击确定

    说明

    修改loose_instant_ddl_enabled参数可以立即生效且无需重启实例。

相关操作

使用秒级加列

  • 指定ALGORITHM=INSTANT强制使用秒级加列:

    ALTER TABLE <table_name> ADD COLUMN <column_name> <data_type> <constraints>, ALGORITHM = INSTANT;
  • 不指定 ALGORITHM,RDS MySQL运行时根据条件选择最优模式:

    ALTER TABLE <table_name> ADD COLUMN <column_name> <data_type> <constraints>;

查看已执行秒级加列的表

  • MySQL 5.7:

    SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE INSTANT_COLS > 0;
  • MySQL 8.0:

    -- 内核小版本低于20230630
    SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE INSTANT_COLS > 0;
    
    -- 内核小版本大于等于20230630
    SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE TOTAL_ROW_VERSIONS > 0;

查看通过秒级加列添加的列

  • MySQL 5.7:

    5.7版本在INFORMATION_SCHEMA库中新增了INNODB_SYS_INSTANT_COLUMNS表,通过如下SQL查看秒级加列功能添加的列信息。

    SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INSTANT_COLUMNS WHERE TABLE_ID = 
    (SELECT TABLE_ID FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME = "<database_name>/<table_name>");
  • MySQL 8.0:

    通过如下SQL查看表的列信息,若查询结果中HAS_DEFAULT列为1,则说明该列是通过秒级加列功能添加的。

    SELECT * FROM INFORMATION_SCHEMA.INNODB_COLUMNS WHERE TABLE_ID = 
    (SELECT TABLE_ID FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME = "<database_name>/<table_name>");