【问题标题】:MySQL Online DDL changes completing, but not persistingMySQL Online DDL 更改完成,但不持久
【发布时间】:2021-02-19 10:43:55
【问题描述】:

我有一个非常大的表(> 60 亿行 & > 3tb 的​​数据),我正在尝试更改。

示例架构:

CREATE TABLE `huge_table` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `col1` int(11) unsigned DEFAULT NULL,
  `col2` int(11) unsigned DEFAULT NULL,
  `col3` int(11) unsigned NOT NULL,
  `col4` int(11) unsigned DEFAULT NULL,
  `col5` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `col6` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `col7` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
  `col8` datetime GENERATED ALWAYS AS (cast(`created` as date)) VIRTUAL,
  `dt1` timestamp(3) NULL DEFAULT NULL,
  `dt2` timestamp(3) NULL DEFAULT NULL,
  `dt3` timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_col5` (`col5`),
  KEY `col4` (`col4`),
  KEY `col1` (`col1`),
  KEY `col3` (`col3`),
  KEY `col6` (`col6`,`col3`),
  KEY `col2` (`col2`),
  KEY `col8` (`col8`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

这些索引中的大多数都是不必要的,所以我正在尝试清理它们,并添加更精确的索引。请注意,下面的所有ALTER TABLE 语句都需要超过 24 小时才能运行。

首先,我尝试使用 Online DDL 修改所有索引:

ALTER TABLE huge_table 
  DROP INDEX col4_idx,
  DROP INDEX col1_idx,
  DROP INDEX col3_idx,
  DROP INDEX col6_idx,
  DROP INDEX col2_idx,
  DROP INDEX col8_idx,
  ADD INDEX new_idx(col3, col6, col1), 
  ALGORITHM=INPLACE, LOCK=NONE;

当这最终完成时(没有错误),我检查了架构,却发现架构中没有任何变化。因此,我决定不强制它运行“INPLACE”再试一次:

ALTER TABLE huge_table 
  DROP INDEX col4_idx,
  DROP INDEX col1_idx,
  DROP INDEX col3_idx,
  DROP INDEX col6_idx,
  DROP INDEX col2_idx,
  DROP INDEX col8_idx,
  ADD INDEX new_idx(col3, col6, col1);

这也不起作用(它似乎仍在在线模式下运行)。我决定将这个过程分成两部分:首先删除不必要的列,然后添加新列:

ALTER TABLE huge_table 
  DROP INDEX col4_idx,
  DROP INDEX col1_idx,
  DROP INDEX col3_idx,
  DROP INDEX col6_idx,
  DROP INDEX col2_idx,
  DROP INDEX col8_idx;
  
ALTER TABLE huge_table 
  ADD INDEX new_idx(col3, col6, col1);

删除列只用了几秒钟,新索引完成且没有错误(再次,在联机模式下)。不幸的是,新索引没有采用。

我认为整个 DDL 语句在创建新索引失败后最终被回滚,但没有看到任何记录;它似乎默默地失败了。我想知道是不是因为有一个VIRTUAL 列,但我希望引擎会返回某种错误消息。有没有其他人看到过这种类型的问题?

【问题讨论】:

    标签: mysql ddl


    【解决方案1】:

    所以,就在提交这个问题之前,我发现了错误:

    Error Code: 1799. Creating index 'new_idx' required more than 'innodb_online_alter_log_max_size' bytes of modification log. Please try again.

    问题在于该表被大量使用,innodb_online_alter_log_max_size 设置是对在线 DDL 过程中存储的 DML 语句数量的硬性限制。结果,我似乎无法在在线模式下修改此表,除非我提高此值。

    https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_online_alter_log_max_size

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-24
      • 2011-06-24
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多