对于一个包含上亿条记录的大型表,直接删除大量数据可能会导致性能问题,如长时间锁定表、事务日志过大等。为了提高删除操作的性能并减少对系统的影响,可以采用分批处理的方法,并结合一些优化技巧。以下是一个详细的Shell脚本示例,用于分批处理和删除数据。
Shell脚本示例
#!/bin/bash
# 数据库连接信息
DB_HOST="localhost"
DB_PORT="3306"
DB_NAME="your_database_name"
DB_USER="your_username"
DB_PASSWORD="your_password"
BATCH_SIZE=10000 # 每批次处理的数据量
MAX_ATTEMPTS=5 # 最大尝试次数
SLEEP_INTERVAL=10 # 每次尝试之间的等待时间(秒)
# 临时SQL文件
SQL_FILE="/tmp/hme_eo_job_sn_operations.sql"
# 创建临时表
cat > $SQL_FILE <<EOF
CREATE TABLE IF NOT EXISTS hme_eo_job_sn_split LIKE hme_eo_job_sn;
EOF
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASSWORD $DB_NAME < $SQL_FILE
# 分批处理
while true; do
# 创建临时SQL文件
cat > $SQL_FILE <<EOF
-- 开始一个事务
START TRANSACTION;
-- 插入一批数据
INSERT INTO hme_eo_job_sn_split SELECT * FROM hme_eo_job_sn
WHERE creation_date < '2024-01-01'
LIMIT $BATCH_SIZE;
-- 删除这批数据
DELETE FROM hme_eo_job_sn WHERE creation_date < '2024-01-01' LIMIT $BATCH_SIZE;
-- 提交事务
COMMIT;
EOF
# 执行SQL文件
for attempt in $(seq 1 $MAX_ATTEMPTS); do
mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASSWORD $DB_NAME < $SQL_FILE
if [ $? -eq 0 ]; then
break
else
echo "Attempt $attempt failed, retrying in $SLEEP_INTERVAL seconds..."
sleep $SLEEP_INTERVAL
fi
done
# 检查是否还有数据需要处理
cat > $SQL_FILE <<EOF
SELECT COUNT(*) AS count FROM hme_eo_job_sn WHERE creation_date < '2024-01-01';
EOF
ROW_COUNT=$(mysql -h $DB_HOST -P $DB_PORT -u $DB_USER -p$DB_PASSWORD $DB_NAME -sN < $SQL_FILE)
if [ "$ROW_COUNT" -le 0 ]; then
break
fi
done
# 删除临时SQL文件
rm -f $SQL_FILE
echo "操作成功完成。"
详细说明
- 数据库连接信息:
- 设置数据库的主机名、端口、数据库名称、用户名和密码。
-
BATCH_SIZE
:每批次处理的数据量,可以根据实际情况调整。 -
MAX_ATTEMPTS
:最大尝试次数,防止网络或服务器问题导致的失败。 -
SLEEP_INTERVAL
:每次尝试之间的等待时间(秒)。
- 创建临时表:
- 使用
CREATE TABLE IF NOT EXISTS
语句创建hme_eo_job_sn_split
表(如果它不存在)。
- 分批处理:
- 循环执行插入和删除操作,直到所有符合条件的数据都被处理完。
- 每次循环中,生成一个临时SQL文件,包含插入和删除操作。
- 使用
INSERT ... SELECT
语句将符合条件的数据插入到hme_eo_job_sn_split
表中。 - 使用
DELETE ... WHERE id IN (SELECT ...)
语句删除这些数据。 - 通过
START TRANSACTION
和COMMIT
确保每个批次的操作是原子的。
- 重试机制:
- 如果某次执行失败,脚本会自动重试,最多尝试
MAX_ATTEMPTS
次。 - 每次重试之间会等待
SLEEP_INTERVAL
秒。
- 检查剩余数据:
- 在每次循环结束时,检查
hme_eo_job_sn
表中是否还有符合条件的数据。 - 如果没有更多数据需要处理,则退出循环。
- 删除临时SQL文件:
- 清理临时SQL文件以保持环境整洁。
性能优化建议
- 索引:
- 确保
creation_date
列上有索引,以加快查询速度。 - 如果
id
列不是主键,确保id
列上有索引。
- 批量大小:
- 调整
BATCH_SIZE
以找到最佳性能。太小会导致频繁的事务开销,太大可能导致长时间锁定表。
- 事务隔离级别:
- 可以考虑降低事务隔离级别,例如使用
READ UNCOMMITTED
,但这可能会影响数据一致性。
- 日志记录:
- 在生产环境中,建议在脚本中添加日志记录,以便跟踪操作进度和故障排查。
- 监控:
- 在执行过程中,监控数据库的性能指标,如 CPU、内存、磁盘 I/O 等,以确保系统稳定运行。