MySQL, Oracle, Linux, 软件架构及大数据技术知识分享平台

网站首页 > 精选文章 / 正文

《MySQL性能调优实战指南》附录A&B

2025-03-25 13:47 huorong 精选文章 2 ℃ 0 评论

附录A:紧急故障处理清单

锁等待超时(1205)的5步解决方案

错误信息Lock wait timeout exceeded; try restarting transaction (1205)

  1. 实时锁状态分析
-- 查看当前锁等待链
SELECT 
  r.trx_id AS waiting_trx_id,
  r.trx_query AS waiting_query,
  b.trx_id AS blocking_trx_id,
  b.trx_query AS blocking_query,
  TIMEDIFF(NOW(), r.trx_started) AS wait_duration
FROM information_schema.innodb_lock_waits w
INNER JOIN information_schema.innodb_trx b 
  ON b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r 
  ON r.trx_id = w.requesting_trx_id;
  1. 阻塞会话处理
-- 强制终止阻塞事务(需评估业务影响)
KILL [blocking_trx_id];

-- 预防性措施(调整锁超时时间)
SET GLOBAL innodb_lock_wait_timeout = 30;  -- 默认50秒→30秒
  1. 索引优化
-- 检查未使用索引的查询
EXPLAIN [problematic_query];

-- 紧急添加覆盖索引
ALTER TABLE [table] ADD INDEX idx_emergency ([column]);
  1. 事务拆分
# 使用pt-deadlock-logger监控死锁
pt-deadlock-logger --user=root --password=xxx --run-time=30m
  1. 长期预防
# 配置锁监控(8.0+)
innodb_status_output_locks = ON
innodb_print_all_deadlocks = ON

主从延迟的3级加速方案

Level 1:常规加速

# 从库配置优化
slave_parallel_workers = 16
slave_preserve_commit_order = ON
innodb_flush_log_at_trx_commit = 2

Level 2:激进加速

-- 启用多线程复制(MTS)
STOP SLAVE;
SET GLOBAL slave_parallel_type = 'LOGICAL_CLOCK';
SET GLOBAL slave_parallel_workers = 32;
START SLAVE;

-- 跳过无关事务(慎用!)
SET GLOBAL sql_slave_skip_counter = [N]; 

Level 3:灾难恢复

# 重建从库(Percona XtraBackup)
innobackupex --slave-info --parallel=4 /backup/
rsync -avP /backup/ [slave_server]:/var/lib/mysql/

# 启用延迟写入(允许延迟1小时)
CHANGE MASTER TO master_delay = 3600;

OOM Killer触发后的取证方法

  1. 日志收集
# 查看内核日志(定位被杀进程)
dmesg -T | grep -i 'oom\|kill'

# MySQL错误日志分析
grep -A 20 'Out of memory' /var/log/mysql/error.log
  1. 内存取证
# 检查进程内存画像(需gdb)
gdb -p [mysql_pid] --batch -ex 'info proc mappings' > /tmp/mem_map.txt

# 分析内存分配(jemalloc需单独工具)
MALLOC_CONF=stats_print:true mysqld --print-stats
  1. 紧急止血
# 临时降低内存使用
innodb_buffer_pool_size = 4G  # 原值8G→4G
table_open_cache = 512        # 原值2000→512
thread_cache_size = 32        # 原值256→32
  1. 根因分析工具
# 生成内存火焰图
perf record -F 99 -p [mysql_pid] -g -- sleep 30
perf script | stackcollapse-perf.pl | flamegraph.pl > oom.svg

# 检查内存泄漏(Valgrind)
valgrind --tool=memcheck --leak-check=full mysqld --debug

故障复盘模板

### 故障概述
- 发生时间:2024-03-15 14:23
- 影响时长:38分钟
- 业务影响:订单支付延迟

### 时间线追溯
| 时间戳           | 事件                                      | 响应动作                   |
|---------------|-------------------------------|--------------------- --|
| 14:23:05        | 监控触发OOM告警               | 启动应急预案             |
| 14:25:11        | 确认MySQL进程被kill           | 重启实例并降级配置   |

### 根本原因
1. 内存泄漏:连接池未释放闲置连接
2. 配置缺陷:buffer_pool设置超过物理内存70%

### 改进措施
- [ ] 增加内存使用率实时看板
- [ ] 建立压测环境模拟OOM场景
- [ ] 部署自动内存缩放策略

执行优先级建议

  1. 生产环境打印本清单并张贴在运维工位
  2. 每季度进行故障模拟演练(Fire Drill)
  3. 所有操作需在测试环境验证后再实施

附录B:调优工具包

压力测试脚本(sysbench定制版)

功能特性

  • 多场景模板:内置电商/社交/物联网等6种业务模型
  • 智能报告:自动生成TPS曲线图与资源消耗热力图
  • 故障注入:模拟网络抖动、IO Hang等异常场景

脚本内容

#!/bin/bash
# sysbench增强版 v2.3

CONFIG_FILE="test_config.ini"
RESULT_DIR="/tmp/bench_$(date +%s)"
mkdir -p $RESULT_DIR

# 读取配置
DB_HOST=$(awk -F '=' '/^host/{print $2}' $CONFIG_FILE)
THREADS=$(awk -F '=' '/^threads/{print $2}' $CONFIG_FILE)

# 执行测试矩阵
for mode in oltp_read_write oltp_order_adv oltp_user_reg; do
  sysbench $mode \
    --mysql-host=$DB_HOST \
    --mysql-user=bench \
    --mysql-password=Bench123! \
    --threads=$THREADS \
    --time=300 \
    --report-interval=10 \
    run > $RESULT_DIR/${mode}_result.log
  
  # 生成可视化报告
  awk '/transactions:/{print $3}' $RESULT_DIR/${mode}_result.log | \
    gnuplot -e "set terminal png; set output '$RESULT_DIR/${mode}_tps.png'" \
    -e "plot '-' with lines title 'TPS'"
done

# 结果打包
tar czf sysbench_report.tar.gz $RESULT_DIR

使用示例

# 配置测试参数
cat > test_config.ini <<EOF
host=10.0.0.101
threads=64
tables=20
table_size=1000000
EOF

# 执行测试
./sysbench-pro.sh

配置检查工具(pt-variable-advisor增强版)

功能升级

  • 风险分级:根据业务类型标记致命/警告/建议项
  • 自动修复:支持生成参数优化ALTER脚本
  • 版本感知:识别MySQL 5.7/8.0的配置差异

使用指南

# 安装依赖
sudo apt-get install percona-toolkit

# 基础检查
pt-variable-advisor --user root --password 'xxx' localhost

# 生成调优建议(HTML报告)
pt-variable-advisor --user root --password 'xxx' \
  --report-format html \
  --output config_audit.html \
  localhost

# 自动修复(高危项)
pt-variable-advisor --user root --password 'xxx' \
  --fix-mode critical \
  --execute-changes \
  localhost

报告重点解读

Critical: 
  - key_buffer_size=4G  # 未使用MyISAM却分配大内存

Warning: 
  - innodb_flush_method=O_DIRECT_NO_FSYNC  # 数据丢失风险

Advice: 
  - query_cache_type=1 → 0  # 高并发下建议关闭

索引冗余分析器(Python版)

功能亮点

  • 多维分析:结合使用频率、存储开销、查询收益
  • 智能推荐:建议合并/删除的冗余索引
  • 安全防护:自动生成禁用命令而非直接DROP

脚本源码

#!/usr/bin/env python3
# index_advisor.py v1.5

import mysql.connector
import pandas as pd
from typing import List, Dict

class IndexAnalyzer:
    def __init__(self, host: str, user: str, password: str):
        self.conn = mysql.connector.connect(
            host=host, user=user, password=password,
            database='information_schema'
        )
    
    def get_redundant_indexes(self) -> List[Dict]:
        query = """
        SELECT *
        FROM sys.schema_redundant_indexes
        WHERE table_schema NOT IN ('mysql', 'sys')
        """
        return pd.read_sql(query, self.conn).to_dict('records')
    
    def generate_advice(self, redundancy: List[Dict]) -> str:
        report = []
        for idx in redundancy:
            advice = f"ALTER TABLE `{idx['table_schema']}`.`{idx['table_name']}`\n"
            advice += f"  DROP INDEX `{idx['redundant_index_name']}`;\n"
            advice += f"  /* 冗余度: {idx['redundant_index_columns']} vs {idx['dominant_index_columns']} */\n"
            report.append(advice)
        return "\n".join(report)
    
    def safe_disable(self, index_name: str) -> str:
        return f"ALTER INDEX `{index_name}` INVISIBLE;"

if __name__ == "__main__":
    analyzer = IndexAnalyzer('localhost', 'admin', 'Secure123!')
    redundancies = analyzer.get_redundant_indexes()
    print("### 索引优化建议 ###")
    print(analyzer.generate_advice(redundancies))

执行示例

# 安装依赖
pip install mysql-connector-python pandas

# 运行分析
python index_advisor.py

# 输出示例
### 索引优化建议 ###
ALTER TABLE `order_db`.`orders`
  DROP INDEX `idx_user_status`;
  /* 冗余度: user_id,status vs user_id,status,create_time */

Tags:difftime

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言