Files
openclaw-config/skills/table-alias/scripts/sync_table.sh
T

191 lines
6.8 KiB
Bash
Executable File

#!/bin/bash
# 表结构对齐脚本 - 准生产 → VPS
# 支持单表模式,避免全量同步
# 不使用 set -e,手动处理错误
# 连接信息
SOURCE_HOST="100.115.195.188"
SOURCE_PORT="50036"
SOURCE_USER="witsoftd"
TARGET_HOST="101.34.227.188"
TARGET_PORT="3306"
TARGET_USER="root"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
usage() {
echo "用法:$0 <database> <table>"
echo " $0 <database> # 同步整个库"
echo ""
echo "示例:"
echo " $0 dmp_serp idb_pub_basic_item_info # 单表同步"
echo " $0 dmp_serp # 全库同步"
exit 1
}
[ -z "$1" ] && usage
SOURCE_DB="$1"
TABLE="$2"
TARGET_DB="${3:-$SOURCE_DB}" # 可选第三个参数指定目标库名,默认同源库名
# 检查环境变量
if [ -z "$MYSQL_PWD_WIT" ]; then
log_error "缺少环境变量 MYSQL_PWD_WIT"
exit 1
fi
if [ -z "$MYSQL_PWD_SQL" ]; then
log_error "缺少环境变量 MYSQL_PWD_SQL"
exit 1
fi
# 输出目录
DATE=$(date +%Y%m%d)
OUTPUT_DIR="/home/yangxuan/codes/xuan-sql/scripts/${DATE}"
mkdir -p "$OUTPUT_DIR"
log_info "同步方向:准生产 (${SOURCE_HOST}:${SOURCE_PORT}) → VPS (${TARGET_HOST}:${TARGET_PORT})"
log_info "数据库:${SOURCE_DB}"
[ -n "$TABLE" ] && log_info "表:${TABLE} (单表模式)"
# 获取表列表
if [ -n "$TABLE" ]; then
# 单表模式
log_info "单表模式:只同步 ${TABLE}"
TABLES="$TABLE"
else
# 全库模式
log_info "全库模式:获取表列表..."
TABLES=$(mysql -h "$SOURCE_HOST" -P "$SOURCE_PORT" -u "$SOURCE_USER" -p"${MYSQL_PWD_WIT}" -D "$SOURCE_DB" -N -e "SHOW TABLES;")
TABLE_COUNT=$(echo "$TABLES" | wc -l)
log_info "共 ${TABLE_COUNT} 张表"
if [ "$TABLE_COUNT" -gt 50 ]; then
log_warn "表数量超过 50,确认继续?(y/n)"
read -r CONFIRM
[ "$CONFIRM" != "y" ] && exit 0
fi
fi
# 同步单表函数
sync_single_table() {
local TABLE_NAME="$1"
local SCRIPT_FILE="${OUTPUT_DIR}/${SOURCE_DB}__${TABLE_NAME}__struct.sql"
log_info "处理:${TABLE_NAME}"
# 检查源表是否存在
SOURCE_EXISTS=$(mysql -h "$SOURCE_HOST" -P "$SOURCE_PORT" -u "$SOURCE_USER" -p"${MYSQL_PWD_WIT}" -D "$SOURCE_DB" -N -e \
"SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$SOURCE_DB' AND TABLE_NAME='$TABLE_NAME';")
if [ "$SOURCE_EXISTS" -eq 0 ]; then
log_error "源表 ${SOURCE_DB}.${TABLE_NAME} 不存在"
return 1
fi
# 检查目标表是否存在
TARGET_EXISTS=$(mysql -h "$TARGET_HOST" -P "$TARGET_PORT" -u "$TARGET_USER" -p"${MYSQL_PWD_SQL}" -D "$TARGET_DB" -N -e \
"SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$TARGET_DB' AND TABLE_NAME='$TABLE_NAME';")
# 获取源表结构(去除字面量 \n,转换为真实换行;cut -f2 取 CREATE 语句列)
SOURCE_CREATE=$(mysql -h "$SOURCE_HOST" -P "$SOURCE_PORT" -u "$SOURCE_USER" -p"${MYSQL_PWD_WIT}" -D "$SOURCE_DB" -N -e "SHOW CREATE TABLE \`${TABLE_NAME}\`;" | cut -f2 | sed 's/\\n/\n/g')
if [ "$TARGET_EXISTS" -eq 0 ]; then
# 表不存在 → CREATE
log_info " 目标表不存在,使用 CREATE TABLE"
# 提取 CREATE TABLE 语句的主体部分(删除第一行和最后一行)
TABLE_BODY=$(echo "$SOURCE_CREATE" | sed '1d;$d')
cat > "$SCRIPT_FILE" <<EOF
-- ============================================================
-- 表结构同步:${TABLE_NAME}
-- 源:准生产 (${SOURCE_HOST}:${SOURCE_PORT})
-- 目标:VPS (${TARGET_HOST}:${TARGET_PORT}) ${TARGET_DB}
-- 生成时间:$(date '+%Y-%m-%d %H:%M:%S')
-- ============================================================
CREATE TABLE IF NOT EXISTS \`${TARGET_DB}\`.\`${TABLE_NAME}\` (
$TABLE_BODY
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='同步自准生产'
EOF
else
# 表存在 → 对比差异
log_info " 目标表已存在,对比结构差异..."
# 获取字段差异
DIFF_FIELDS=$(mysql -h "$SOURCE_HOST" -P "$SOURCE_PORT" -u "$SOURCE_USER" -p"${MYSQL_PWD_WIT}" -D "$SOURCE_DB" -N -e "
SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='$SOURCE_DB' AND TABLE_NAME='$TABLE_NAME'
ORDER BY ORDINAL_POSITION;
" | md5sum)
TARGET_DIFF=$(mysql -h "$TARGET_HOST" -P "$TARGET_PORT" -u "$TARGET_USER" -p"${MYSQL_PWD_SQL}" -D "$TARGET_DB" -N -e "
SELECT COLUMN_NAME, COLUMN_TYPE, IS_NULLABLE, COLUMN_DEFAULT, COLUMN_COMMENT
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA='$TARGET_DB' AND TABLE_NAME='$TABLE_NAME'
ORDER BY ORDINAL_POSITION;
" | md5sum)
if [ "$DIFF_FIELDS" = "$TARGET_DIFF" ]; then
log_info " 结构一致,跳过"
return 0
fi
log_warn " 发现差异,生成 ALTER 脚本..."
# TODO: 生成精确的 ALTER 语句
SOURCE_STRUCT=$(mysql -h "$SOURCE_HOST" -P "$SOURCE_PORT" -u "$SOURCE_USER" -p"${MYSQL_PWD_WIT}" -D "$SOURCE_DB" -N -e "SHOW CREATE TABLE \`$TABLE_NAME\`;" 2>/dev/null | tail -1 || echo "无法获取")
TARGET_STRUCT=$(mysql -h "$TARGET_HOST" -P "$TARGET_PORT" -u "$TARGET_USER" -p"${MYSQL_PWD_SQL}" -D "$TARGET_DB" -N -e "SHOW CREATE TABLE \`$TABLE_NAME\`;" 2>/dev/null | tail -1 || echo "无法获取")
cat > "$SCRIPT_FILE" <<EOF
-- ============================================================
-- 表结构修改:${TABLE_NAME}
-- 源:准生产 (${SOURCE_HOST}:${SOURCE_PORT})
-- 目标:VPS (${TARGET_HOST}:${TARGET_PORT}) ${TARGET_DB}
-- 生成时间:$(date '+%Y-%m-%d %H:%M:%S')
-- ============================================================
-- ⚠️ 需要人工对比差异后手动完善 ALTER 语句
-- 源表结构:
-- $SOURCE_STRUCT
-- 目标表结构:
-- $TARGET_STRUCT
-- ALTER TABLE \`${TARGET_DB}\`.\`${TABLE_NAME}\` ...;
EOF
fi
# 执行脚本
if [ -f "$SCRIPT_FILE" ]; then
log_info " 执行脚本:${SCRIPT_FILE}"
if mysql -h "$TARGET_HOST" -P "$TARGET_PORT" -u "$TARGET_USER" -p"${MYSQL_PWD_SQL}" < "$SCRIPT_FILE" 2>&1; then
log_info " ✅ 成功"
else
log_error " ❌ 失败,查看脚本:${SCRIPT_FILE}"
fi
fi
}
# 执行同步
FAILED=0
SUCCESS=0
for TABLE_NAME in $TABLES; do
if sync_single_table "$TABLE_NAME"; then
((SUCCESS++))
else
((FAILED++))
fi
done
log_info "完成!成功:${SUCCESS}, 失败:${FAILED}"
log_info "脚本目录:${OUTPUT_DIR}"