文章

使用 Shell 脚本 + Crontab 定时清理 MySQL 表数据

使用 Shell 脚本 + Crontab 定时清理 MySQL 表数据

在日常运维或系统运行过程中,某些日志类或临时数据表会快速增长。 例如性能分析类表:

  • miniprofilers
  • miniprofilerclienttimings
  • miniprofilertimings

如果不定期清理,可能导致:

  • 表体积膨胀
  • 备份变慢
  • 查询性能下降

本文记录一个完整的实践流程:

使用 Shell 脚本执行 MySQL 命令,并通过 crontab 实现每周自动清理。


一、通过 Shell 执行 MySQL 命令的几种方式

在 Linux 环境中,执行 SQL 通常有三种方式:


1️⃣ 直接执行单条 SQL

1
mysql -u用户名 -p密码 -h主机 数据库名 -e "SQL语句"

例如:

1
2
mysql -u cvuser -p -h 127.0.0.1 miniprofilers_warehouse \
-e "TRUNCATE TABLE miniprofilers;"

适用于简单单条语句。


2️⃣ 使用 Here Document(推荐)

当需要执行多条 SQL 时,更推荐使用 Here Document:

1
2
3
4
5
mysql 数据库名 <<EOF
SQL1;
SQL2;
SQL3;
EOF

优点:

  • 可读性强
  • 结构清晰
  • 适合脚本化

二、安全存储数据库密码(推荐做法)

不要在脚本中写:

1
-p密码

否则会:

  • 出现在 ps -ef 进程列表
  • 被记录进 shell history
  • 存在安全风险

更推荐使用 ~/.my.cnf:

1
2
3
4
[client]
user=cvuser
password=your_password
host=your_host

然后设置权限:

1
chmod 600 ~/.my.cnf

之后即可直接执行:

1
mysql miniprofilers_warehouse

MySQL 客户端会自动读取配置。


三、最终生产可用脚本

脚本路径:

1
/usr/local/bin/clear_miniprofiler.sh

完整脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash

DB_NAME="miniprofilers_warehouse"
LOG_FILE="/var/log/clear_miniprofiler.log"

echo "==================================" >> $LOG_FILE
echo "开始执行时间: $(date '+%Y-%m-%d %H:%M:%S')" >> $LOG_FILE

mysql "$DB_NAME" <<EOF >> $LOG_FILE 2>&1
TRUNCATE TABLE miniprofilers;
TRUNCATE TABLE miniprofilerclienttimings;
TRUNCATE TABLE miniprofilertimings;
EOF

if [ $? -eq 0 ]; then
    echo "执行成功" >> $LOG_FILE
else
    echo "执行失败" >> $LOG_FILE
fi

echo "结束时间: $(date '+%Y-%m-%d %H:%M:%S')" >> $LOG_FILE
echo "==================================" >> $LOG_FILE
echo "" >> $LOG_FILE

关键点说明

1️⃣ 日志记录

1
>> $LOG_FILE 2>&1

含义:

  • >> 追加写入
  • 2>&1 将错误输出重定向到日志

这样可以完整记录执行过程。


2️⃣ 退出码判断

1
if [ $? -eq 0 ];
  • $? 表示上一个命令的退出状态
  • 0 表示成功
  • 非 0 表示失败

这是 Shell 中标准的错误控制方式。


3️⃣ 赋予执行权限

1
chmod +x /usr/local/bin/clear_miniprofiler.sh

四、使用 crontab 实现每周自动执行

编辑定时任务:

1
crontab -e

添加:

1
0 3 * * 2 /usr/local/bin/clear_miniprofiler.sh

字段含义:

1
2
分 时 日 月 星期
0  3  *  *   2

表示:

每周二凌晨 3:00 自动执行一次


五、工程化实践建议

在生产环境中,建议增加:


✅ 1. 读写实例检测(防御性编程)

在脚本中增加只读检测,避免误执行:

1
2
3
4
5
6
IS_READ_ONLY=$(mysql -N -s -e "show variables like 'read_only';" | awk '{print $2}')

if [ "$IS_READ_ONLY" = "ON" ]; then
    echo "当前实例为只读,终止执行" >> $LOG_FILE
    exit 1
fi

✅ 2. 日志轮转

配合 logrotate,避免日志无限增长。


✅ 3. 改为按时间删除(更平滑)

如果是高并发生产环境,可以替换为:

1
2
DELETE FROM miniprofilers 
WHERE CreatedTime < NOW() - INTERVAL 7 DAY;

避免长时间锁表。


六、完整流程总结

整个实现流程可以归纳为:

  1. 使用 ~/.my.cnf 安全存储数据库凭据
  2. 使用 Here Document 在 Shell 中执行多条 SQL
  3. 添加日志记录与退出状态判断
  4. 使用 crontab 定期调度
  5. 增强安全与容错能力

本文由作者按照 CC BY 4.0 进行授权