MySQL 进阶技巧

MySQL 低质量 SQL 诊断

方式 1:监控当前执行的 SQL 会话

  • SHOW FULL PROCESSLIST; 会返回执行时间过长或状态为 'Query' 的语句

方式 2:通过 performance_schema 库识别 TOP10 的高消耗 SQL

SELECT event_name, sql_text, timer_wait
FROM performance_schema.events_statements_history
ORDER BY timer_wait DESC
LIMIT 10;

方式 3:使用 EXPLAIN 查看特定 SQL 查询的执行计划,识别可能的全表扫描问题

Docker 环境下的 MySQL

用Docker运行MySQL的好处:快速搭建、环境一致性,易于版本切换

用 Docker 运行 MySQL 可能存在的问题:

问题 1:额外的性能损耗

# 测试原生Linux磁盘写入速度
dd if=/dev/zero of=test.bin bs=1G count=1 oflag=direct

# 测试Docker容器内磁盘写入速度
docker run --rm -it ubuntu dd if=/dev/zero of=test.bin bs=1G count=1 oflag=direct
  • 实际测试中,Docker内部的I/O性能通常比原生系统低10%-20%
  • 每条网络请求在Docker中都需要额外的网络栈处理,增加了延迟和CPU开销
  • Docker的存储和网络栈带来明显的性能开销,不适合I/O密集型的MySQL

问题 2:存在数据丢失风险

  • 容器意外删除 docker rm -f mysql:容器挂载的数据卷变成孤儿卷
  • 备份与恢复复杂,需要同时备份容器的配置和数据卷
  • 当容器崩溃出现崩溃时,可能导致数据没有完全持久化到物理磁盘

问题 3:无法做到合理的资源管理

  • MySQL的性能高度依赖正确的内存配置,但容器的内存限制可能导致问题
  • 在容器环境中,CPU资源的分配和隔离不如物理机稳定
  • 当宿主机资源紧张时,容器间的CPU竞争会导致MySQL性能不稳定

问题 4:高可用、安全性与隔离性存在问题

  • MySQL集群存在容器通信延迟、容器 IP 变动和容器调度异常等问题
  • 容器提供的隔离性不如虚拟机,可能存在内核共享、资源泄露等问题
  • 问题的监控与诊断困难,难以区分是MySQL问题还是容器环境问题

千万级大表新增字段

核心问题:执行 ALTER TABLE ADD COLUMN(DDL 操作)时,MySQL 会锁表

  • 锁表时间 ≈ 表数据量 / 磁盘IO速度
  • 对于1 kw 行、单行1KB的表,机械磁盘(100MB/s),缩表时间为 100 秒

方案 1:MySQL 5.6+ 可使用原生Online DDL

  • 仅支持部分操作,仍可能触发表锁(如添加全文索引)
  • 需要额外的磁盘空间,存在主从延迟风险
  • 锁表时间在秒级~分钟级,适合 1 亿以内的表

方案 2:停机维护,仅限于允许停服的场景

  • 适合数据量<100GB,注意准备完整的回滚预案

方案 3:PT-OSC工具,创建影子表和触发器,逐步替代原表

  • 比如 Percona Toolkit 的 pt-online-schema-change

方案 4:双写+逻辑迁移,金融级安全方案

  • 适合10亿+的表新增字段,操作复杂,耗时长

方案 5:gh-ost(GitHub's Online Schema Transmogrifier)

  • GitHub 开源的一种无触发器的MySQL在线表结构变更方案
  • 适合解决大表DDL(新增字段|索引变更|表引擎转换)时锁表阻塞、主库负载高等问题
  • 核心思路:通过异步解析binlog,替代触发器同步增量数据,显著降低对线上业务的影响

方案 6:分区表滑动窗口方案,仅修改最新分区结构

参考: 为什么不建议在 Docker 中跑 MySQL?
千万级的大表如何新增字段?

往年同期文章