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:分区表滑动窗口方案,仅修改最新分区结构