97 lines
4.5 KiB
Bash
Executable File
97 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# =============================================================================
|
||
# 共享法规知识库冷迁移脚本 (migrate_shared_kb.sh)
|
||
#
|
||
# 作用:
|
||
# 将参考项目容器 agent-regkb (端口 55432) 的 2,907 篇法规、31 万条切片
|
||
# 通过流式无损方式迁移至本项目专有基础设施容器 shuimu-kb-shared (端口 5432)
|
||
#
|
||
# 原则:
|
||
# 1. 源容器 agent-regkb 纯只读零侵入,严禁写操作;
|
||
# 2. 目标容器使用本项目专属数据卷 chat-agent-shared-kb-pgdata;
|
||
# 3. 迁移完成后执行数据基线校验。
|
||
# =============================================================================
|
||
|
||
set -eo pipefail
|
||
|
||
SOURCE_CONTAINER="agent-regkb"
|
||
TARGET_CONTAINER="shuimu-kb-shared"
|
||
DB_NAME="regulations"
|
||
DB_USER="regkb"
|
||
|
||
echo "============================================================"
|
||
echo ">>> 开始法规知识库流式数据迁移 (解耦自立)"
|
||
echo ">>> 源容器: ${SOURCE_CONTAINER} (只读)"
|
||
echo ">>> 目标容器: ${TARGET_CONTAINER} (本项目专有)"
|
||
echo "============================================================"
|
||
|
||
# 1. 检查源容器是否运行
|
||
if ! docker ps --format '{{.Names}}' | grep -q "^${SOURCE_CONTAINER}$"; then
|
||
echo "[错误] 源容器 ${SOURCE_CONTAINER} 未运行,无法执行数据读取!"
|
||
exit 1
|
||
fi
|
||
|
||
# 2. 检查目标容器是否运行
|
||
if ! docker ps --format '{{.Names}}' | grep -q "^${TARGET_CONTAINER}$"; then
|
||
echo "[提示] 目标容器 ${TARGET_CONTAINER} 未启动,尝试启动..."
|
||
docker compose -f docker-compose.shared.yml up -d
|
||
fi
|
||
|
||
# 3. 等待目标容器就绪
|
||
echo "[等待] 检查 ${TARGET_CONTAINER} 数据库就绪状态..."
|
||
for i in {1..30}; do
|
||
if docker exec -i "${TARGET_CONTAINER}" pg_isready -U "${DB_USER}" -d "${DB_NAME}" >/dev/null 2>&1; then
|
||
echo "[就绪] ${TARGET_CONTAINER} 已接受连接。"
|
||
break
|
||
fi
|
||
sleep 1
|
||
if [ "$i" -eq 30 ]; then
|
||
echo "[错误] 目标数据库连接超时!"
|
||
exit 1
|
||
fi
|
||
done
|
||
|
||
# 4. 执行流式无损导出与导入
|
||
echo "[迁移] 正在从 ${SOURCE_CONTAINER} 导出并流式导入到 ${TARGET_CONTAINER}..."
|
||
START_TIME=$(date +%s)
|
||
|
||
docker exec -i "${SOURCE_CONTAINER}" pg_dump -U "${DB_USER}" -d "${DB_NAME}" --clean --if-exists \
|
||
| sed -e '/DROP EXTENSION IF EXISTS vector/d' \
|
||
| docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" >/dev/null
|
||
|
||
END_TIME=$(date +%s)
|
||
DURATION=$((END_TIME - START_TIME))
|
||
echo "[完成] 数据流式导入完成,耗时: ${DURATION} 秒。"
|
||
|
||
# 5. 数据完整性比对校验
|
||
echo "============================================================"
|
||
echo ">>> 执行数据完整性基线校验"
|
||
echo "============================================================"
|
||
|
||
SRC_DOC_COUNT=$(docker exec -i "${SOURCE_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_documents;")
|
||
TGT_DOC_COUNT=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_documents;")
|
||
|
||
SRC_CHUNK_COUNT=$(docker exec -i "${SOURCE_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_chunks;")
|
||
TGT_CHUNK_COUNT=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_chunks;")
|
||
|
||
SRC_NODE_COUNT=$(docker exec -i "${SOURCE_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_nodes;")
|
||
TGT_NODE_COUNT=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT count(*) FROM reg_nodes;")
|
||
|
||
TGT_DB_SIZE=$(docker exec -i "${TARGET_CONTAINER}" psql -U "${DB_USER}" -d "${DB_NAME}" -t -A -c "SELECT pg_size_pretty(pg_database_size('regulations'));")
|
||
|
||
echo "法规文档数 (reg_documents): 源=${SRC_DOC_COUNT} | 目标=${TGT_DOC_COUNT}"
|
||
echo "法规切片数 (reg_chunks): 源=${SRC_CHUNK_COUNT} | 目标=${TGT_CHUNK_COUNT}"
|
||
echo "法规节点数 (reg_nodes): 源=${SRC_NODE_COUNT} | 目标=${TGT_NODE_COUNT}"
|
||
echo "目标数据库大小: ${TGT_DB_SIZE}"
|
||
|
||
if [[ "${SRC_DOC_COUNT}" == "${TGT_DOC_COUNT}" && "${SRC_CHUNK_COUNT}" == "${TGT_CHUNK_COUNT}" && "${SRC_NODE_COUNT}" == "${TGT_NODE_COUNT}" ]]; then
|
||
echo "============================================================"
|
||
echo ">>> [PASS] 知识库数据无损迁移成功!数据 100% 一致!"
|
||
echo "============================================================"
|
||
else
|
||
echo "============================================================"
|
||
echo ">>> [FAIL] 数据校验不一致,请排查导入日志!"
|
||
echo "============================================================"
|
||
exit 1
|
||
fi
|