对于一个包含上亿条记录的大型表,直接删除大量数据可能会导致性能问题,如长时间锁定表、事务日志过大等。为了提高删除操作的性能并减少对系统的影响,可以采用分批处理的方法,并结合一些优化技巧。以下是一个详细的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 "操作成功完成。"

详细说明

  1. 数据库连接信息
  • 设置数据库的主机名、端口、数据库名称、用户名和密码。
  • BATCH_SIZE:每批次处理的数据量,可以根据实际情况调整。
  • MAX_ATTEMPTS:最大尝试次数,防止网络或服务器问题导致的失败。
  • SLEEP_INTERVAL:每次尝试之间的等待时间(秒)。
  1. 创建临时表
  • 使用 CREATE TABLE IF NOT EXISTS 语句创建 hme_eo_job_sn_split 表(如果它不存在)。
  1. 分批处理
  • 循环执行插入和删除操作,直到所有符合条件的数据都被处理完。
  • 每次循环中,生成一个临时SQL文件,包含插入和删除操作。
  • 使用 INSERT ... SELECT 语句将符合条件的数据插入到 hme_eo_job_sn_split 表中。
  • 使用 DELETE ... WHERE id IN (SELECT ...) 语句删除这些数据。
  • 通过 START TRANSACTIONCOMMIT 确保每个批次的操作是原子的。
  1. 重试机制
  • 如果某次执行失败,脚本会自动重试,最多尝试 MAX_ATTEMPTS 次。
  • 每次重试之间会等待 SLEEP_INTERVAL 秒。
  1. 检查剩余数据
  • 在每次循环结束时,检查 hme_eo_job_sn 表中是否还有符合条件的数据。
  • 如果没有更多数据需要处理,则退出循环。
  1. 删除临时SQL文件
  • 清理临时SQL文件以保持环境整洁。

性能优化建议

  1. 索引
  • 确保 creation_date 列上有索引,以加快查询速度。
  • 如果 id 列不是主键,确保 id 列上有索引。
  1. 批量大小
  • 调整 BATCH_SIZE 以找到最佳性能。太小会导致频繁的事务开销,太大可能导致长时间锁定表。
  1. 事务隔离级别
  • 可以考虑降低事务隔离级别,例如使用 READ UNCOMMITTED,但这可能会影响数据一致性。
  1. 日志记录
  • 在生产环境中,建议在脚本中添加日志记录,以便跟踪操作进度和故障排查。
  1. 监控
  • 在执行过程中,监控数据库的性能指标,如 CPU、内存、磁盘 I/O 等,以确保系统稳定运行。