使用 Shell 脚本 + Crontab 定时清理 MySQL 表数据
使用 Shell 脚本 + Crontab 定时清理 MySQL 表数据
在日常运维或系统运行过程中,某些日志类或临时数据表会快速增长。 例如性能分析类表:
miniprofilersminiprofilerclienttimingsminiprofilertimings
如果不定期清理,可能导致:
- 表体积膨胀
- 备份变慢
- 查询性能下降
本文记录一个完整的实践流程:
使用 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;
避免长时间锁表。
六、完整流程总结
整个实现流程可以归纳为:
- 使用
~/.my.cnf安全存储数据库凭据 - 使用 Here Document 在 Shell 中执行多条 SQL
- 添加日志记录与退出状态判断
- 使用 crontab 定期调度
- 增强安全与容错能力
本文由作者按照 CC BY 4.0 进行授权