#!/usr/bin/env bash # 本地 MySQL -> 生产 RDS(经 105 服务器导入) set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" SSH_TARGET="${SSH_TARGET:-root@120.26.184.105}" REMOTE_SQL="/tmp/wordloop-sync.sql.gz" LOCAL_HOST="${LOCAL_MYSQL_HOST:-localhost}" LOCAL_PORT="${LOCAL_MYSQL_PORT:-3306}" LOCAL_USER="${LOCAL_MYSQL_USER:-boot}" LOCAL_PASS="${LOCAL_MYSQL_PASSWORD:-888888}" LOCAL_DB="${LOCAL_MYSQL_DATABASE:-wordloop}" RDS_HOST="${RDS_HOST:-rm-uf6h1j53vtuxi78i90o.mysql.rds.aliyuncs.com}" RDS_PORT="${RDS_PORT:-3306}" RDS_USER="${RDS_USER:-boot}" RDS_PASS="${RDS_PASSWORD:-@Abc888888}" RDS_DB="${RDS_DATABASE:-wordloop}" # 仅同步全局离线词典(无用户外键)。 # 词书目录请走 publish.sh -> install-production.sh 内的 import_word_books(按 slug upsert,避免 DROP 破坏学习关联)。 # 绝不包含 users / user_settings / words / quiz_records / wiki_* 等账号学习数据表。 TABLES="dictionary_entries" DUMP="$(mktemp /tmp/wordloop-sync.XXXXXX.sql.gz)" cleanup() { rm -f "${DUMP%.gz}" "$DUMP" 2>/dev/null || true; } trap cleanup EXIT echo ">>> 1/3 导出本地库 (${LOCAL_DB})..." mysqldump -h "$LOCAL_HOST" -P "$LOCAL_PORT" -u "$LOCAL_USER" -p"$LOCAL_PASS" \ --single-transaction --quick --extended-insert --add-drop-table \ --set-gtid-purged=OFF --no-tablespaces \ "$LOCAL_DB" $TABLES | gzip -c > "$DUMP" ls -lh "$DUMP" echo ">>> 2/3 上传到 ${SSH_TARGET}..." scp "$DUMP" "${SSH_TARGET}:${REMOTE_SQL}" echo ">>> 3/3 导入生产 RDS (${RDS_HOST})..." ssh "$SSH_TARGET" "gunzip -c ${REMOTE_SQL} | mysql -h '${RDS_HOST}' -P '${RDS_PORT}' -u '${RDS_USER}' -p'${RDS_PASS}' '${RDS_DB}' && rm -f ${REMOTE_SQL}" echo ">>> 校验生产库行数..." ssh "$SSH_TARGET" "cd /root/wordloop/backend && source venv/bin/activate && python3 - <<'PY' from sqlalchemy import text from database import engine with engine.connect() as c: for t in ['users','words','word_books','word_book_entries','dictionary_entries','quiz_records']: print(f\"{t}:\", c.execute(text(f'SELECT COUNT(*) FROM {t}')).scalar()) PY" echo ">>> 同步完成"