工作中使用的数据库系统一直没更新,目前还是MySQL 5.5@Ubuntu 14.04,前两天还出了一次问题,执行任何查询,执行一会儿就提示未知错误,查了半天也没查到具体问题,关键日志也没有,怀疑是磁盘问题,好在用mysqldump还可以导出备份数据。重配置一个虚拟机,然后数据备份回去。为了避免类似问题再发生,想着是时候升级一下了。研究了一下,目前MySQL相对稳定的最新版本建议8.0,正好Ubuntu224.04下apt方式安装的也是8.0.44。安装配置好程序后,剩下就是数据迁移工作。人工查询了半天,发现MySQL的数据迁移还是个麻烦事,不同版本之间兼容性堪忧,如果非要迁移,也必须按照大版本顺序而不能跳,比如5.5->5.6->5.7->8.0。想着反正数据有了备份,测试环境不怕折腾,直接用脚本在主机上登录进MySQL执行。果然遇到了问题,主要问题有俩:

第一个问题是表记录尺寸太大,具体:

1
[InnoDB] Cannot create the table `ss`.`bmxx` because the record size will exceed the maximum allowed size for a record.

  手动查了半天,也没找到合适的解决方案,想想试试AI,打开Google 搜索的AI模式,结果非常高效的提供了问题分析和解决方案,而且Google的AI模式不存在语言的障碍,中文和英文的互联网知识都能够查询。Google AI认为问题发生的原因主要是:
  这个问题通常发生在 InnoDB 引擎中,因为 InnoDB 的单行记录(Row Size)有严格的字节限制。默认配置下(16KB 页大小),单行数据不能超过约 8126 字节。
  给出了针对该错误的几种常见解决方案,按照推荐程度来看,第一条是修改行格式为DYNAMIC:如果你的表还在使用旧的 COMPACT 或 REDUNDANT 格式,大字段会占用过多行内空间。DYNAMIC 格式能更高效地处理溢出页。
  后续我又补充了问题场景及文件大小信息,并要求ai提供完整的代码,最后给出:

  1. 准备阶段
    1
    2
    3
    SET GLOBAL innodb_strict_mode = 0;          -- 默认的root权限不足,需要进入mysql配置目录,用debian-sys-maint用户登录执行
    SET GLOBAL max_allowed_packet = 1073741824; -- 1GB
    SET GLOBAL foreign_key_checks = 0; -- 导入期间关闭外键约束
  2. 编写执行脚本
    1
    2
    3
    4
    5
    6
    7
    # user:用户名 backup.sql: 之前备份好待导入的文件
    sed -e 's/ROW_FORMAT=COMPACT/ROW_FORMAT=DYNAMIC/g' \
    -e 's/ROW_FORMAT=REDUNDANT/ROW_FORMAT=DYNAMIC/g' \
    backup.sql | mysql -u user -p --default-character-set=utf8
    -- 不带数据库名:命令末尾不要写数据库名称,mysql 会根据 SQL 文件内的 USE db_name 自动切换。
    -- 替换 REDUNDANT:旧版本 5.5 有时会使用 REDUNDANT 格式,脚本中一并替换为 DYNAMIC 可最大程度确保在 8.0 中创建成功。
    -- 编码统一:指定 --default-character-set=utf8 是为了让 8.0 按照 5.5 的 utf8mb3 规范 解析,防止因编码转换导致的空间溢出
    实际执行后,目前没有发现任何问题。
    附:Google AI解决问题的对话

第二个问题是日志系统有问题:

1
[InnoDB] Threads are unable to reserve space in redo log which can't be reclaimed due to the 'log_checkpointer' consumer still lagging behind at LSN = 7519122533. Consider increasing innodb_redo_log_capacity.
  1. 问题描述
      Google AI认为:这个错误提示表明你的 MySQL(8.0.30 及更高版本)由于 Redo Log(重做日志)空间耗尽 导致事务线程被挂起。
    简单来说,InnoDB 的 log_checkpointer 进程负责将内存中的“脏页”写入磁盘,以便回收 Redo Log 空间。当由于写入负载过高或 innodb_redo_log_capacity 设置过小,导致“脏页”落盘速度跟不上新日志生成的频率时,系统就会报错并强制所有事务停下来等待空间释放。
  2. 问题原因
      负载激增:突发的大批量数据导入或高并发更新超出了当前日志容量能缓冲的范围。
      消费者滞后:除了检查点进程,如果有备份工具(如 MySQL Enterprise Backup)或 Clone 插件正在运行且未及时确认 LSN,也会阻止空间回收。
      配置过小:MySQL 8.0.30 默认的 innodb_redo_log_capacity 仅为 100MB,对于生产环境通常远远不够。
  3. 核心解决方案:在线调大容量
    1
    2
    -- 将容量设置为 1GB (根据你的磁盘空间和业务负载调整)
    SET GLOBAL innodb_redo_log_capacity = 1024 * 1024 * 1024;
  4. 最后给出建议:
      建议将 innodb_redo_log_capacity 设置得足够大,能够容纳约一小时的峰值写入量。你可以通过监控 LSN 增长速率来估算所需的容量。此外,考虑调整 innodb_io_capacity 参数以提高脏页刷盘效率。
      报错是否发生在你正在执行大批量数据导入或备份任务时?

AI对话
  AI真香,Google AI比我利用搜索引擎查找解决问题的能力强。