孤立表

本页讨论了 MySQL 中与孤立表相关的已知问题。

什么是孤立表?

孤立表是指在 MySQL 数据字典中定义断开连接的表,可能会出现在 MySQL 5.6 或 MySQL 5.7 中。以下任一情形都可能会阻止从 MySQL 5.7 到 MySQL 8.0 的主要版本升级 (MVU):

  • 存在 InnoDB 数据文件 (.ibd),但没有相应的定义文件 (.frm),反之亦然。
  • 由不再被任何有效应用逻辑引用或使用的 ALTER TABLE 语句遗留下来的中间表。

孤立的临时表

孤立临时表名称以 #sql- 前缀开头,例如 #sql-123

使用以下查询可帮助识别孤立的临时表:

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME RLIKE '#sql-[0-9].*';

您可以使用 DROP TABLE 命令来舍弃孤立的临时表,而无需执行任何其他额外步骤。这适用于大多数情况:

DROP TABLE `DB`.`#mysql50#TEMPORARY_ORPHAN_TABLE`;

DB 替换为您要使用的数据库名称。

一个示例可能如下所示:

DROP TABLE `testdb`.`#mysql50##sql-1234`;

如果之前的 DROP 表命令不起作用,则定义文件 (.frm) 可能被其他 ALTER TABLE 操作重复使用。在这种情况下,需要在磁盘上创建一个占位符 .frm 文件来移除该表。请与 Cloud SQL 支持团队联系以寻求帮助。 如果您没有支持合同,请参阅自助方法,了解问题排查步骤。

孤立的中间表

孤立的中间表名称以 #sql-ib 前缀开头,例如 #sql-ib23-343224

使用以下查询来识别孤立的中间表:

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE '%#sql-ib%';

如需移除中间孤立表,请先更改孤立定义文件名 (.frm),使其与表名称一致,然后从命令行中删除该表。

如需移除中间孤立表,请与 Cloud SQL 支持团队联系以获取帮助。如果您没有支持合同,请参阅自助方法,了解问题排查步骤。

孤立的普通表

当孤立的 InnoDB 表对应的 .ibd 数据文件仍保留在文件系统中,但数据字典不再正确引用该数据文件时,就会出现孤立的 InnoDB 表。此方案需要人工干预。

如需解决此问题,请与 Cloud SQL 支持团队联系。支持团队可以创建一个占位符 .frm 文件,然后使用 DROP TABLE 命令尝试移除该表。如果未成功,则 InnoDB (.ibd) 文件可能需要从数据目录中手动移除。

手动移除文件后,您可以备份所有表和数据库结构。

使用 DROP DATABASE 删除数据库,并使用 CREATE DATABASE 创建数据库。最后一步可能需要让连接到受影响数据库的应用停机。

如果您没有支持合同,请参阅自助方法,了解问题排查步骤。

自助式问题排查

以下自助问题排查方法涉及在删除单个表不起作用时,通过删除或迁移整个数据库来移除孤立表。此方法会造成中断。如果贵组织签订了支持服务合约,我们强烈建议您与 Cloud SQL 支持团队联系以寻求帮助。

如需移除孤立的临时表,请务必先按照孤立的临时表中的步骤操作。如果 DROP TABLE 命令失败,请尝试以下建议。

准备工作

  • 我们强烈建议您进行完整的实例备份,以降低数据丢失的风险。

  • 为帮助缩短可能出现的应用停机时间,我们强烈建议您克隆实例,并在生产环境中完成以下迁移步骤之前先进行验证。

    如需了解详情,请参阅克隆实例

使用对象迁移功能删除架构

数据库对象迁移是将数据库对象(例如表)迁移到临时架构的多步流程:

  1. 备份其他数据库对象,包括过程、函数和视图。
  2. 舍弃并重新创建受影响的架构。
  3. 将备份的对象重新导入到原始架构中。

此迁移方法通常会导致应用停机。为尽量减少中断,请提前准备好所有必要的脚本。例如,确保您的脚本已准备好处理以下情况:

  • 重命名表并将其移至临时架构。
  • 备份其他数据库对象,例如过程、函数、视图和任何其他对象。
  • 将所有数据库对象恢复到原始架构。

这些脚本准备就绪后,请完成以下步骤:

  1. 在同一实例上创建临时架构(例如:fix_orphan_tables)。
  2. 停止受影响的架构上的应用流量。
  3. 使用 RENAME TABLE 将所有表移至临时架构:

    RENAME TABLE DB.TABLE_NAME TO fix_orphan_tables.TABLE_NAME;
    

    进行以下替换:

    • DB:您要使用的数据库名称。
    • TABLE_NAME:表名称。
  4. 备份数据库对象,例如视图、例程、存储过程、触发器和事件。一种方法是使用 mysqldump

    mysqldump -u USER --password=PASSWORD \
      -h HOST_IP --set-gtid-purged=OFF --no-data --no-create-db  \
      --no-create-info --routines --triggers --skip-opt --events \
      DB > DB_export.sql
    

    进行以下替换:

    • USER:用户名。
    • PASSWORD:数据库密码。
    • HOST_IP:主机的 IP 地址。
    • DB:您要使用的数据库名称。

    强烈建议您使用 SHOW CREATE VIEW 命令代码段手动备份视图。

  5. 舍弃包含孤立表的架构。

  6. 使用原始名称创建架构。

  7. 验证孤立表是否已移除:

    SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE '%ORPHAN_TABLE_NAME</var>';
    

    ORPHAN_TABLE_NAME 替换为孤立表的名称。

  8. 将表复制回原始架构:

    RENAME TABLE fix_orphan_tables.TABLE_NAME TO DB.TABLE_NAME;
    

    进行以下替换:

    • TABLE_NAME:表名称。
    • DB:您要使用的数据库名称。
  9. 复制在第 4 步中创建的备份中的所有数据库对象。

    mysql -u USER \
      --password=PASSWORD \
      -h <var>HOST_IP \
      -D<var>DB < <var>DB_export.sql
    

    进行以下替换:

    • USER:用户名。
    • PASSWORD:数据库密码。
    • HOST_IP:主机的 IP 地址。
    • DB:您要使用的数据库名称。

    强烈建议您使用 CREATE VIEW 语句重新创建视图,以手动恢复视图。

  10. 恢复之前停止的所有应用流量。

使用转储和加载将架构丢弃到同一实例

移除孤立表的另一种方法是,对受影响的架构执行完整转储,然后删除并重新创建该架构,最后恢复转储。在某些情况下,此方法可能更快且更简单。为尽量减少中断,请务必提前准备好所有备份和恢复脚本。

这些脚本准备就绪后,请完成以下步骤:

  1. 停止受影响的架构上的应用流量。
  2. 使用 mysqldump 备份孤立表所在的架构,包括所有存储过程、触发器、视图和事件。
  3. 删除架构。
  4. 重新创建架构并恢复备份文件。
  5. 恢复在第一步中停止的所有应用流量。

转储并加载到新实例或重新创建的实例

在特定条件下,无法舍弃包含孤立表的架构。在这些情况下,您必须迁移到新实例,或者使用逻辑转储和加载重新创建现有实例。这两种方法都可能会导致应用中断,并且可能需要重新配置应用,以指向新创建或重新创建的数据库实例。以下部分介绍了这两种方法。

使用 Database Migration Service (DMS) 将数据迁移到新实例

  1. 使用 Database Migration Service 创建新的 Cloud SQL for MySQL 实例。
  2. 在副本实例完成与新实例相关联的数据复制后,停止连接到源实例的所有应用。
  3. 升级 Cloud SQL for MySQL 副本实例。
  4. 将所有应用连接更改为指向新升级的 Cloud SQL for MySQL 实例,然后重启应用。

手动转储和恢复

  1. 如果您要创建新的数据库实例,请创建与当前实例配置相同的实例。
  2. 停止当前数据库实例上的所有应用流量。
  3. 使用 mysqldump 或类似实用程序备份所有架构。
  4. 如果使用同一实例,请删除并重新创建该实例。
  5. 使用您在第 3 步中创建的备份,将备份恢复到新实例或同一重新创建的实例。
  6. 将应用指向新实例或重新创建的同一实例,然后恢复应用操作。

后续步骤

  1. 问题排查
  2. 就地升级数据库主要版本