hive表元数据修复脚本
背景:由于历史问题,之前有些业务使用hive表数据,直接通过脚本将表数据目录整体移走,导致元数据一直存在,随着时间增长,impala每次写入数据后,刷新元数据,随着元数据越来越多,加载catalog的内存就会oom,之前历史任务都是连接在同一台的impala上,连接impala执行刷新分区的连接线程一直closdwait,链接不中断,导致连接数越来越多,不释放,任务资源不释放,集群资源占满,任务都在pending,通过执行drop partition命令会报错分区目录不存在,针对这些历史表,在之前移动完分区后,同时执行下面删除元数据脚本可以避免元数据过大的问题
#!/bin/bash
set -e # 开启“出错即退出”模式(可选,增强安全性)# -------------------------- 1. 交互式输入 --------------------------
# 静默输入MySQL密码(安全,不显示在终端)
read -s -p "请输入Hive元数据库(hive)的密码: " MYSQL_PASS
echo # 换行# 输入要删除的分区day值(如:20231218,对应PART_NAME中的day=20231218)
read -p "请输入要删除的分区day值(会删除PART_NAME包含'day=$DAY'的记录): " DAY
[ -z "$DAY" ] && { echo "错误:DAY不能为空!"; exit 1; }# 输入目标表名(如:ads.dec_g_cdr )
read -p "请输入要操作的Hive表名(格式:库名.表名): " TABLE_NAME
[ -z "$TABLE_NAME" ] && { echo "错误:TABLE_NAME不能为空!"; exit 1; }# -------------------------- 2. MySQL基础配置 --------------------------
MYSQL_HOST="localhost" # Hive元数据库地址(如远程:192.168.1.100)
MYSQL_PORT="3306" # 端口(默认3306)
MYSQL_USER="root" # 元数据库用户名(如:hive)
MYSQL_DB="hive" # 元数据库名(默认hive)# -------------------------- 3. 创建备份目录(带时间戳) --------------------------
BACKUP_DIR="bak_meta_$(date +%Y%m%d_%H%M%S)" # 备份目录名(如:bak_meta_20240520_143000)
mkdir -p "$BACKUP_DIR" || { echo "错误:无法创建备份目录!"; exit 1; }
echo "✅ 备份目录创建成功:$BACKUP_DIR"# -------------------------- 4. 备份相关元数据(关键!) --------------------------
echo "📦 开始备份元数据..."# 备份PARTITION_PARAMS表(目标表的所有记录)
mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" \"$MYSQL_DB" PARTITION_PARAMS > "$BACKUP_DIR/PARTITION_PARAMS_backup.sql" || { echo "错误:备份PARTITION_PARAMS失败!"; exit 1; }# 备份PARTITIONS表(目标表+指定day的分区)
mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" \"$MYSQL_DB" PARTITIONS \> "$BACKUP_DIR/PARTITIONS_backup.sql" || { echo "错误:备份PARTITIONS失败!"; exit 1; }# 备份PARTITION_KEY_VALS表(目标分区关联的存储描述)
mysqldump -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" \"$MYSQL_DB" PARTITION_KEY_VALS \> "$BACKUP_DIR/PART_ID_backup.sql" || { echo "错误:备份SDS失败!"; exit 1; }echo "✅ 元数据备份完成!"# -------------------------- 5. 执行删除操作 --------------------------
echo "⚠️ 开始删除元数据(不可逆,请确认备份成功!)..."# 1. 删除PARTITION_PARAMS(子表,先删)
DELETE_PARTITION_PARAMS="DELETE FROM PARTITION_PARAMS WHERE PART_ID IN (SELECT par.PART_ID FROM TBLS tbl JOIN PARTITIONS par ON tbl.tbl_id = par.tbl_id WHERE par.PART_NAME LIKE \"%day=$DAY%\" AND tbl.TBL_NAME = \"$TABLE_NAME\");"
mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" "$MYSQL_DB" -e "$DELETE_PARTITION_PARAMS" || { echo "错误:删除PARTITION_PARAMS失败!"; exit 1; }
echo "✅ PARTITION_PARAMS删除成功!"# 2. 删除PARTITION_KEY_VALS(子表,再删)
DELETE_PARTITION_KEY_VALS="DELETE FROM PARTITION_KEY_VALS WHERE PART_ID IN (SELECT par.PART_ID FROM TBLS tbl JOIN PARTITIONS par ON tbl.tbl_id = par.tbl_id WHERE par.PART_NAME LIKE \"%day=$DAY%\" AND tbl.TBL_NAME = \"$TABLE_NAME\");"
echo "开始执行 ${DELETE_PARTITION_KEY_VALS}"
mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" "$MYSQL_DB" -e "$DELETE_PARTITION_KEY_VALS" || { echo "错误:删除PARTITION_KEY_VALS失败!"; exit 1; }
echo "✅ PARTITION_KEY_VALS删除成功!"# 3. 删除PARTITIONS(父表,最后删)
DELETE_PAR="DELETE FROM PARTITIONS WHERE tbl_id IN (SELECT tbl_id FROM TBLS WHERE TBL_NAME = \"$TABLE_NAME\") AND PART_NAME LIKE \"%day=$DAY%\";"
echo "开始执行 ${DELETE_PAR}"
mysql -h"$MYSQL_HOST" -P"$MYSQL_PORT" -u"$MYSQL_USER" -p"$MYSQL_PASS" "$MYSQL_DB" -e "$DELETE_PAR" || { echo "错误:删除PARTITIONS失败!"; exit 1; }
echo "✅ PARTITIONS删除成功!"# -------------------------- 6. 收尾提示 --------------------------
echo "🎉 所有操作完成!"
echo "💾 备份数据保留在:$BACKUP_DIR(如需清理,请手动删除)"