☰
Shell脚本自动化提升MySQL运维效率实践
2026/11/3 6:47:00 网站建设 项目流程

1. 为什么Shell脚本能提升MySQL运维效率

作为数据库管理员,每天都要面对大量重复性的MySQL操作:备份恢复、用户权限管理、性能监控、数据校验...这些工作如果每次都手动敲命令,不仅效率低下还容易出错。我在某次凌晨3点处理生产环境故障时,就因为手误打错了一个DROP语句差点酿成大祸。

Shell脚本的价值在于把零散操作封装成可复用的自动化流程。比如我们团队现在用脚本实现的例行工作:

  • 每天凌晨自动全量备份+binlog增量备份
  • 每小时检查一次慢查询并邮件报警
  • 新项目上线时批量创建100+用户权限
  • 跨机房数据一致性校验

这些原本需要人工值守的操作,现在全部通过crontab定时触发脚本完成。根据我们的统计,日常运维效率提升了2-3倍,人为失误率下降90%。更重要的是——终于不用再半夜爬起来处理备份了!

2. 基础环境准备

2.1 MySQL客户端工具选择

推荐使用官方的mysql命令行客户端,相比图形化工具更适合脚本化操作。通过-e参数可以直接执行SQL语句,配合-N -B参数可以获取纯净的制表符分隔数据:

# 安装MySQL客户端(以Ubuntu为例) sudo apt-get install mysql-client # 基础连接测试 mysql -h127.0.0.1 -uroot -p'your_password' -e "SHOW DATABASES;"

安全提示:生产环境不要在命令行直接暴露密码,推荐使用~/.my.cnf配置文件:

[client] user=root password=your_secure_password host=127.0.0.1

2.2 Shell脚本编写规范

遵循这些规范可以避免90%的常见错误:

  1. 脚本开头必须加解释器和字符集声明:
    #!/bin/bash set -euo pipefail export LANG=C.UTF-8
  2. 所有MySQL操作函数前添加连接检查:
    check_mysql_connection() { if ! mysql -e "SELECT 1" &>/dev/null; then echo "MySQL连接失败" >&2 return 1 fi }
  3. 使用变量存储敏感信息:
    readonly MYSQL_USER="admin" readonly MYSQL_HOST="db-cluster.rds.aliyuncs.com"

3. 核心功能脚本实现

3.1 自动化备份方案

这是我们的生产级备份脚本框架:

#!/bin/bash # 全量备份+binlog增量备份脚本 readonly BACKUP_DIR="/data/backups/mysql" readonly BACKUP_PREFIX="fullbackup_$(date +%Y%m%d)" readonly LOG_FILE="/var/log/mysql_backup.log" # 创建当日备份目录 mkdir -p "${BACKUP_DIR}/${BACKUP_PREFIX}" # 全量备份(使用mysqldump) mysqldump --single-transaction --master-data=2 \ --all-databases > "${BACKUP_DIR}/${BACKUP_PREFIX}/full.sql" # 刷新binlog确保完整性 mysql -e "FLUSH BINARY LOGS" # 打包压缩备份文件 tar czf "${BACKUP_DIR}/${BACKUP_PREFIX}.tar.gz" -C "${BACKUP_DIR}" "${BACKUP_PREFIX}" # 清理7天前的旧备份 find "${BACKUP_DIR}" -name "fullbackup_*" -mtime +7 -exec rm -f {} \;

关键参数说明:

  • --single-transaction:保证备份期间数据一致性
  • --master-data=2:记录binlog位置点
  • FLUSH BINARY LOGS:创建新的binlog文件

3.2 用户权限批量管理

新项目上线时经常需要批量创建用户:

#!/bin/bash # 批量创建MySQL账号(从CSV文件读取) # 格式:username,password,dbname,host,privileges readonly USER_FILE="new_users.csv" while IFS=, read -r user pass db host priv; do # 创建用户并授权 mysql <<EOF CREATE USER '${user}'@'${host}' IDENTIFIED BY '${pass}'; GRANT ${priv} ON ${db}.* TO '${user}'@'${host}'; FLUSH PRIVILEGES; EOF done < "${USER_FILE}"

4. 高级运维技巧

4.1 实时监控慢查询

这个脚本会每5分钟检查一次慢查询并发送报警:

#!/bin/bash # 慢查询监控脚本 readonly THRESHOLD=2 # 超过2秒视为慢查询 readonly ALERT_EMAIL="dba-team@company.com" # 获取当前慢查询数量 slow_count=$(mysql -NBe "SELECT COUNT(*) FROM performance_schema.events_statements_summary_by_digest WHERE AVG_TIMER_WAIT > ${THRESHOLD}*1000000000") if (( slow_count > 0 )); then # 获取慢查询详情 mysql -e "SELECT DIGEST_TEXT, COUNT_STAR, AVG_TIMER_WAIT/1000000000 AS avg_sec FROM performance_schema.events_statements_summary_by_digest WHERE AVG_TIMER_WAIT > ${THRESHOLD}*1000000000 ORDER BY AVG_TIMER_WAIT DESC" | mail -s "MySQL慢查询报警" "${ALERT_EMAIL}" fi

4.2 主从同步状态监控

这个脚本检查主从复制延迟和错误:

#!/bin/bash # 主从复制监控脚本 slave_status=$(mysql -e "SHOW SLAVE STATUS\G") # 检查IO线程和SQL线程状态 if ! grep -q "Slave_IO_Running: Yes" <<< "${slave_status}" || ! grep -q "Slave_SQL_Running: Yes" <<< "${slave_status}"; then echo "主从复制线程异常!" >&2 mysql -e "SHOW SLAVE STATUS\G" >&2 exit 1 fi # 检查复制延迟(超过60秒报警) delay=$(grep "Seconds_Behind_Master" <<< "${slave_status}" | awk '{print $2}') if (( delay > 60 )); then echo "主从复制延迟 ${delay} 秒" >&2 fi

5. 生产环境避坑指南

5.1 连接池管理

在脚本中频繁创建MySQL连接会导致"Too many connections"错误。推荐两种解决方案:

  1. 使用连接池工具:
# 安装mysqlsh(MySQL Shell) sudo apt-get install mysql-shell # 使用连接池执行查询 mysqlsh --uri root@localhost --js -e "session.runSql('SELECT 1')"
  1. 脚本内复用连接:
# 使用命名管道复用连接 exec 3<> <(mysql -NBe "SELECT 1") while read -u 3 line; do echo "结果: $line" done exec 3>&-

5.2 密码安全最佳实践

绝对不要在脚本中硬编码密码!推荐三种安全方案:

  1. 使用MySQL配置文件的[client]段
  2. 从环境变量读取:
    export MYSQL_PWD=$(aws secretsmanager get-secret-value --secret-id prod/mysql) mysql -uroot -e "SELECT 1"
  3. 使用交互式输入:
    read -s -p "MySQL密码: " password mysql -uroot -p"${password}" -e "SELECT 1"

6. 性能优化脚本示例

6.1 索引碎片整理

这个脚本会找出碎片率超过30%的表并优化:

#!/bin/bash # 自动优化表碎片 readonly FRAG_THRESHOLD=30 # 碎片率阈值 mysql -NBe "SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE data_free > 0" | while read table; do # 计算碎片率 frag_ratio=$(mysql -NBe "SELECT ROUND(data_free/(data_length+index_length)*100,2) FROM information_schema.tables WHERE CONCAT(table_schema,'.',table_name)='${table}'") if (( $(echo "${frag_ratio} > ${FRAG_THRESHOLD}" | bc -l) )); then echo "优化表 ${table} (碎片率 ${frag_ratio}%)" mysql -e "OPTIMIZE TABLE ${table}" fi done

6.2 查询缓存预热

在业务高峰期前预热缓存:

#!/bin/bash # 缓存预热脚本 readonly WARMUP_FILE="/tmp/top_queries.sql" # 从慢查询日志提取高频SQL pt-query-digest --filter '$event->{arg} =~ m/^select/i' \ /var/log/mysql/mysql-slow.log | awk '/^# Query/ {getline; print}' > "${WARMUP_FILE}" # 并行执行预热 parallel -j 8 < "${WARMUP_FILE}"

7. 错误处理与日志记录

7.1 完善的错误处理机制

这个模板包含了完整的错误处理和日志记录:

#!/bin/bash # 带错误处理的脚本模板 set -euo pipefail exec > >(tee -a "/var/log/mysql_script.log") 2>&1 trap 'handle_error $LINENO' ERR handle_error() { local line=$1 echo "[$(date)] 错误发生在第 ${line} 行" >&2 # 发送报警通知 mail -s "MySQL脚本执行失败" admin@example.com <<< "查看日志:/var/log/mysql_script.log" exit 1 } # 主逻辑 mysql -e "START TRANSACTION" # 业务操作... mysql -e "COMMIT" echo "[$(date)] 脚本执行成功"

7.2 审计日志记录

记录所有敏感操作的审计日志:

#!/bin/bash # 带审计的MySQL操作脚本 readonly AUDIT_LOG="/var/log/mysql_audit.log" log_audit() { echo "[$(date)] [$(whoami)] $@" | tee -a "${AUDIT_LOG}" } # 示例:用户删除操作 delete_user() { local user=$1 log_audit "删除用户 ${user}" mysql -e "DROP USER '${user}'@'%'" }

8. 脚本性能优化技巧

8.1 批量操作替代循环

错误示范(性能差):

for id in {1..1000}; do mysql -e "INSERT INTO test VALUES (${id})" done

正确做法(性能提升100倍):

# 生成批量SQL values=$(printf "(%d)," {1..999}; echo "(1000)") mysql -e "INSERT INTO test VALUES ${values}"

8.2 并行处理技巧

使用GNU parallel加速大批量操作:

# 并行导出所有表数据 mysql -NBe "SHOW TABLES" | parallel -j 8 "mysqldump db {} > {}.sql" # 并行执行SQL文件 find /sql_scripts -name "*.sql" | parallel -j 4 "mysql db < {}"

9. 扩展应用场景

9.1 自动化Schema变更

使用脚本管理DDL变更:

#!/bin/bash # 自动化Schema迁移 readonly SCHEMA_VERSION="20230815" readonly LOCK_FILE="/tmp/schema_migrate.lock" # 获取锁防止并发执行 exec 9>"${LOCK_FILE}" flock -n 9 || exit 1 # 检查当前版本 current_ver=$(mysql -NBe "SELECT version FROM schema_version") if [[ "${current_ver}" != "${SCHEMA_VERSION}" ]]; then echo "开始执行Schema变更..." mysql < "/opt/schema/${SCHEMA_VERSION}.sql" mysql -e "UPDATE schema_version SET version='${SCHEMA_VERSION}'" fi

9.2 数据校验脚本

跨实例数据一致性校验:

#!/bin/bash # 数据一致性校验 readonly SOURCE_DSN="user:pass@source-host:3306" readonly TARGET_DSN="user:pass@target-host:3306" # 使用pt-table-checksum进行校验 pt-table-checksum --replicate=test.checksums \ --no-check-binlog-format \ --databases=production \ h=${SOURCE_DSN} # 获取不一致记录 pt-table-sync --replicate=test.checksums \ h=${SOURCE_DSN} h=${TARGET_DSN} \ --print | while read sql; do mysql -h${TARGET_DSN} -e "${sql}" done

10. 持续集成实践

10.1 自动化测试框架

集成到CI/CD管道的测试脚本:

#!/bin/bash # MySQL测试套件 set -e # 启动测试容器 docker run -d --name mysql_test \ -e MYSQL_ROOT_PASSWORD=test \ -p 3306:3306 mysql:5.7 # 等待MySQL启动 while ! mysqladmin ping -h127.0.0.1 -uroot -ptest --silent; do sleep 1 done # 执行测试 mysql -h127.0.0.1 -uroot -ptest < setup_test_db.sql bats mysql_tests.bats # 清理 docker stop mysql_test docker rm mysql_test

10.2 配置漂移检测

定期检查生产环境配置是否符合规范:

#!/bin/bash # 配置合规性检查 readonly STANDARD_FILE="/opt/mysql_standard.cnf" # 导出当前配置 mysql --print-defaults > current.cnf # 使用diff比较差异 if ! diff -u "${STANDARD_FILE}" current.cnf; then echo "发现配置漂移!" >&2 exit 1 fi

11. 实际案例分享

去年我们通过脚本自动化解决了两个典型问题:

案例一:批量处理用户权限

  • 背景:公司并购需要为200+新员工配置数据库权限
  • 传统方式:DBA手动操作,预计8小时,错误率约5%
  • 脚本方案:编写用户批量导入脚本,30分钟完成,零错误
  • 关键脚本:
    # 从HR系统API获取用户列表 curl -s https://hr-api/users | jq -r '.[] | [.email, .dept] | @csv' > users.csv # 批量创建权限 while IFS=, read -r email dept; do mysql <<EOF CREATE USER '${email}'@'%' IDENTIFIED BY '${RANDOM}'; GRANT SELECT ON ${dept}_db.* TO '${email}'@'%'; EOF done < users.csv

案例二:跨机房数据同步

  • 背景:需要验证主从机房的数据一致性
  • 传统方式:导出比对,耗时2小时,只能抽样检查
  • 脚本方案:编写checksum校验脚本,15分钟完成全量比对
  • 关键代码:
    # 主库生成校验值 pt-table-checksum --replicate=percona.checksums \ --no-check-binlog-format \ --databases=production \ h=master-host,u=admin,p=xxx # 从库检查差异 pt-table-sync --replicate=percona.checksums \ h=master-host,u=admin,p=xxx h=slave-host,u=admin,p=xxx \ --print | tee /tmp/repair.sql # 自动修复差异 mysql -hslave-host -uadmin -pxxx < /tmp/repair.sql

12. 脚本维护建议

  1. 版本控制:所有脚本必须纳入Git仓库,建议结构:

    /mysql-scripts ├── backups │ ├── full_backup.sh │ └── binlog_backup.sh ├── user_mgmt │ ├── create_user.sh │ └── audit_users.sh └── lib ├── mysql_utils.sh └── logging.sh
  2. 文档规范:每个脚本头部包含标准注释:

    #!/bin/bash # 名称:mysql_backup.sh # 功能:MySQL全量+增量备份 # 作者:DBA Team # 参数:无 # 输出:/data/backups/mysql/ # 依赖:mysqldump, mysql-client # 日志:/var/log/mysql_backup.log
  3. 定期评审:每季度检查脚本:

    • 是否还有在使用
    • 密码策略是否需要更新
    • 是否有性能优化空间
    • 错误处理是否完善

13. 性能对比测试

我们对常见操作做了脚本化和手动操作的效率对比(测试环境:AWS RDS MySQL 5.7,10万行数据):

操作类型手动操作耗时脚本执行耗时效率提升
创建100个用户权限45分钟28秒96倍
全库备份32分钟25分钟1.3倍
跨库数据迁移6小时47分钟7.6倍
慢查询分析手动无法实现3分钟∞

关键发现:

  1. 越是重复性操作,脚本优势越明显
  2. 某些复杂分析手动根本无法完成
  3. 备份类操作受限于I/O,提升有限但更可靠

14. 安全加固方案

14.1 最小权限原则

每个脚本使用专用MySQL账号:

# 监控脚本用只读账号 readonly MONITOR_USER="monitor_ro" readonly MONITOR_PASS=$(vault read -field=password mysql/creds/monitor) mysql -u"${MONITOR_USER}" -p"${MONITOR_PASS}" -e "SHOW STATUS"

14.2 SQL注入防护

使用参数化查询避免注入:

# 危险!可能被注入 mysql -e "SELECT * FROM users WHERE id=${input}" # 安全做法 mysql -e "SET @id=${input}; SELECT * FROM users WHERE id=@id"

14.3 敏感信息过滤

在日志中自动脱敏:

log_safe() { local msg=$1 # 过滤密码等敏感信息 echo "${msg}" | sed -E 's/(password|pwd)=[^&]*/\1=***/g' }

15. 未来改进方向

  1. Ansible集成:将常用脚本改造成Ansible role,实现更规范的自动化管理
  2. Prometheus监控:输出脚本执行的metrics指标
  3. Web化管理:开发简单界面供非运维人员安全使用常用功能
  4. AI辅助优化:利用GPT-4自动生成复杂查询的优化建议

我们团队正在开发一个开源工具mysql-script-kit,集合了文中提到的各种实用脚本,预计下个季度发布第一个版本。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询