con un clic
aws-data-migrate
資料遷移工具,從 Production 安全地遷移資料到 Local/Staging 環境。自動清理敏感資料,硬編碼禁止反向遷移。
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
資料遷移工具,從 Production 安全地遷移資料到 Local/Staging 環境。自動清理敏感資料,硬編碼禁止反向遷移。
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
在 4 個 Rails 專案(sf_project / jv_project / core_web / e_trading)跑 local dev 指令——console、server、rspec、migrate、rake、bundle。這些指令一律「進 Tilt 起的 web container」跑,不在 host 直接跑。Use when 要對這些 rails 專案開 console、跑 rspec、跑 migration / rake / bundle,或 local server(sf.local / jv.local / core.local / et.local)連不上要排查時。
Archive Claude Code telemetry logs to dated files (YYYY-MM-DD~YYYY-MM-DD.json). Use when user wants to archive, rotate, or save telemetry logs.
Generates optimized prompts for any AI tool. Use when writing, fixing, improving, or adapting a prompt for LLM, Cursor, Midjourney, image AI, video AI, coding agents, or any other AI tool.
BA 報告撰寫指引。在撰寫、審查或修改 BA 報告(-ba.md)時使用。確保 BA 報告使用純業務語言,不包含任何技術術語。
AWS EC2 operations including checking service status, viewing logs, server health monitoring, and production/staging environment management. Use when user asks to check/view/查看 production/staging servers, service status/狀態/狀況, logs/日誌, or perform remote operations like deployment and database backup.
本地效能測試工具,用於測量程式碼執行時間、記憶體使用、N+1 查詢偵測等。支援 Ruby、JavaScript、Python。
| name | aws-data-migrate |
| description | 資料遷移工具,從 Production 安全地遷移資料到 Local/Staging 環境。自動清理敏感資料,硬編碼禁止反向遷移。 |
| version | 3.1.0 |
安全地從 Production 環境遷移資料到 Local/Staging,用於本地除錯和測試。
Production 資料不可變 - 只允許 Production → Local/Staging 的單向遷移
✅ Production → Local
✅ Production → Staging
❌ Local → Production # 硬性禁止
❌ Staging → Production # 硬性禁止
❌ Local → Staging # 需要討論
aws sts get-caller-identity)session-manager-plugin --version;macOS: brew install --cask session-manager-plugin)RDS 已升級到 PG16,但 EC2 都是 Ubuntu 16.04(glibc 2.23),裝不了 pg16 client。
路徑 ①(推薦,restore 專用):S3 + EC2 本地 psql 直連 RDS
Local Mac: pg_dump (via SSM tunnel + Docker pg16) → .sql → gzip
→ aws s3 cp → S3 bucket
EC2: aws s3 cp ← S3 bucket
→ gunzip → psql 9.6(EC2 自帶)直連目標 RDS (VPC 內) → restore
send-command 只負責 kick off + 輪詢進度\restrict / \unrestrict meta-command → 9.x 不認識,dump 後先 sed -i -e '/^\\restrict /d' -e '/^\\unrestrict /d' 刪掉路徑 ②(dump 階段不得已才用):SSM Port Forwarding + 本地 Docker pg16
Mac (localhost)
├── SSM tunnel :15440 → Production EC2 → Production RDS (PG16)
└── Docker postgres:16 container
└── pg_dump → host.docker.internal:15440 (dump)
--verbose 觀察進度、設 PGOPTIONS="--statement-timeout=0"、每次重要操作前先 psql -c "SELECT 1;" 確認 tunnel 還活著、斷了就重開重試psql -f xxx.sql restore 大檔案 —— 改走路徑 ①macOS 的 Docker 不支援 --network host,必須用 host.docker.internal 連回 Mac 的 localhost。
aws ssm start-session \
--target "{INSTANCE_ID}" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["{RDS_HOST}"],"portNumber":["5432"],"localPortNumber":["{LOCAL_PORT}"]}'
所有 Production → Staging 遷移預設走 Path C(保留
admin_staffs的 staging 測試帳號)。 只有明確要求「完全覆蓋」時才走 Path A。Why:Staging admin 帳號(密碼、OTP、角色)是手動設定的測試環境狀態,被 production 覆蓋後需要重新設定密碼 + OTP,非常麻煩。
在開始遷移前,必須確認:
📦 資料遷移需求確認
1. 遷移模式:{full_sync / partial_reset / selective}
2. 目標環境:{local / staging}
3. 需要遷移的 Table(s):{all / 指定 tables / 全部但排除某些 table 的資料}
4. 敏感資料處理:{mask / keep}(Staging 同 VPC 可選 keep)
請確認以上資訊是否正確?
根據遷移模式選擇對應路徑:
適用場景:Staging 環境需要完整的 Production 資料副本。
# 1. 確認 AWS CLI 認證
aws sts get-caller-identity
# 2. 確認 Production / Staging EC2 都在 running
aws ec2 describe-instances --instance-ids "$PROD_INSTANCE_ID" "$STAGING_INSTANCE_ID" \
--query "Reservations[].Instances[].{Id:InstanceId,State:State.Name}" --output table
從兩邊的 .env 或 shared/.env 取得 DB 連線:
# Production DB 連線(從 shared/.env 取得)
aws ssm send-command --instance-ids "$PROD_INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["cat /home/apps/{app_name}/shared/.env | grep -E \"^(DATABASE_|RAILS_ENV)\""]'
# Staging DB 連線
aws ssm send-command --instance-ids "$STAGING_INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["cat /home/apps/{app_name}/shared/.env | grep -E \"^(DATABASE_|RAILS_ENV)\""]'
Staging 可能能直連 Production RDS(同 VPC / peering),這樣可以省去檔案傳輸:
# 在 Staging EC2 上測試連線 Production RDS
aws ssm send-command --instance-ids "$STAGING_INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["sudo su - apps -c \"PGPASSWORD={prod_password} psql -h {prod_rds_host} -U {prod_user} -d {db_name} -c \\\"SELECT 1 as test;\\\"\""]'
重要:dump 前必須確認磁碟空間足夠(建議可用空間 > dump 預估大小的 1.5 倍)
# 檢查磁碟空間和舊 dump 檔案
aws ssm send-command --instance-ids "$TARGET_INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["df -h /home/apps && echo --- && ls -lhS /home/apps/*.sql /home/apps/*.sql.gz /home/apps/*.dump 2>/dev/null || echo no dump files"]'
空間不足時,確認後刪除舊的 dump 檔案:
# 列出舊檔讓用戶確認後再刪除
rm -f /home/apps/{app_name}_YYYYMMDD.sql # 逐一刪除確認過的舊檔
標準方式:SSM Tunnel + 本地 Docker pg16(推薦)
EC2 上的 pg_dump 版本太舊(PG12),無法 dump PG16 RDS。必須用本地 Docker。
# 1. 開 Production RDS tunnel(在另一個終端或背景)
aws ssm start-session --target "{PROD_INSTANCE_ID}" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["{prod_rds_host}"],"portNumber":["5432"],"localPortNumber":["15440"]}'
# 2. 用 Docker pg16 dump(macOS 用 host.docker.internal)
docker run --rm -e PGPASSWORD={prod_password} -v /tmp:/dump postgres:16 \
pg_dump -h host.docker.internal -p 15440 -U {prod_user} -d {db_name} \
--no-owner --no-acl -f /dump/{app_name}_YYYYMMDD.sql
# 3. 驗證
ls -lh /tmp/{app_name}_YYYYMMDD.sql
備援方式:EC2 上直接 dump(僅當 EC2 的 pg_dump 版本 >= RDS 版本時可用)
# 在 EC2 上直接 dump(需先確認 pg_dump --version >= server version)
PGPASSWORD={prod_password} pg_dump \
-h {prod_rds_host} -U {prod_user} -d {db_name} \
--no-owner --no-acl \
-f /home/apps/{app_name}_YYYYMMDD.sql
重要:這會清掉 Staging 現有資料,執行前必須確認用戶同意。
⚠️ 預設應走 Path C 保留 admin_staffs。只有用戶明確要求「完全覆蓋」時才走 Path A。
推薦流程:DROP/CREATE 用 tunnel(短操作)+ Restore 走 S3 + EC2(長操作不用 tunnel)
# 1. 開 Staging RDS tunnel(只用來做短指令,長 restore 不依賴它)
aws ssm start-session --target "{STAGING_INSTANCE_ID}" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["{staging_rds_host}"],"portNumber":["5432"],"localPortNumber":["15441"]}'
# 2. Terminate + Drop + Create(本地 psql via tunnel,秒殺)
PGPASSWORD={staging_password} psql -h 127.0.0.1 -p 15441 -U {staging_user} -d postgres \
-c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='{db_name}' AND pid<>pg_backend_pid();"
PGPASSWORD={staging_password} psql -h 127.0.0.1 -p 15441 -U {staging_user} -d postgres \
-c "DROP DATABASE IF EXISTS {db_name}; CREATE DATABASE {db_name};"
# 3. Restore —— 走 Path C C3 的 S3 + EC2 nohup 模式,別用 SSM tunnel 做長 restore
# 4. 授權 Blazer user(restore 後 table owner 是 {staging_user},blazer user 無權限)
PGPASSWORD={staging_password} psql -h 127.0.0.1 -p 15441 -U {staging_user} -d {db_name} -c "
GRANT SELECT ON ALL TABLES IN SCHEMA public TO blazer;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO blazer;
"
# 5. 驗證
PGPASSWORD={staging_password} psql -h 127.0.0.1 -p 15441 -U {staging_user} -d {db_name} \
-c "SELECT count(*) as table_count FROM information_schema.tables WHERE table_schema='public' AND table_type='BASE TABLE';"
# 檢查 stderr 是否有錯誤
aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$STAGING_INSTANCE_ID" \
--query "[Status, StandardErrorContent]" --output text
# 用 real count(*) 對比 prod / staging 的幾個代表性 table
# (勿用 pg_stat_user_tables.n_live_tup — 統計常失準,production 尤其常見)
for t in {large_table_1} {large_table_2} {medium_table}; do
P=$(PGPASSWORD={prod_pw} psql -h {prod_rds} -U {prod_user} -d {db} -tAc "SELECT count(*) FROM $t;")
S=$(PGPASSWORD={stg_pw} psql -h {stg_rds} -U {stg_user} -d {db} -tAc "SELECT count(*) FROM $t;")
printf "%-50s prod=%s staging=%s\n" "$t" "$P" "$S"
done
為什麼不用 pg_stat_user_tables
n_live_tup 是統計值,需要 ANALYZE 才更新SELECT count(*) 說了算# 清理 Production 上的暫存(如果有)
rm -f /home/apps/{app_name}_YYYYMMDD.sql.gz
# 清理 S3 上的暫存(如果有)
aws s3 rm s3://{bucket}/db-backup/{app_name}_YYYYMMDD.sql.gz
# Staging 上的 dump 檔可保留作為回滾用,或清理
# rm -f /tmp/db_restore.sh
適用場景:只需要特定 table 或特定時間範圍的資料,用於除錯或分析。
自動偵測以下類型的敏感欄位:
| 類型 | 欄位名稱模式 | 處理方式 |
|---|---|---|
*email*, *mail* | 替換為 xxx@example.com | |
| 電話 | *phone*, *tel*, *mobile* | 替換為 0900-000-000 |
| 地址 | *address* | 替換為 測試地址 |
| 密碼 | *password*, *passwd* | 清空或替換為固定 hash |
| Token | *token*, *secret*, *key* | 清空 |
| 身分證 | *id_number*, *identity* | 替換為 A000000000 |
| 銀行帳號 | *bank*, *account* | 替換為 000-0000000 |
Production → Staging(同 VPC) 且用戶確認不需要清理時,可跳過此步驟。
方法 A:使用 pg_dump(單表或多表)
# 單表匯出
PGPASSWORD={password} pg_dump -h {rds_host} -U {user} -d {db_name} \
-t {table_name} --data-only \
-f /tmp/{table_name}.sql
# 多表匯出
PGPASSWORD={password} pg_dump -h {rds_host} -U {user} -d {db_name} \
-t table1 -t table2 -t table3 --data-only \
-f /tmp/selected_tables.sql
方法 B:使用 Rails Runner(需要條件過濾時)
# /tmp/export_data.rb
require 'csv'
records = Invoice.where(created_at: 30.days.ago..Time.current).limit(1000)
CSV.open('/tmp/export.csv', 'w') do |csv|
csv << records.first.attributes.keys
records.each { |r| csv << r.attributes.values }
end
puts "Exported #{records.count} records"
# 透過 SSM cat 取得小型檔案
COMMAND_ID=$(aws ssm send-command \
--instance-ids "$INSTANCE_ID" \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["cat /tmp/export.csv"]' \
--output text --query "Command.CommandId")
aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$INSTANCE_ID" \
--query "StandardOutputContent" \
--output text > /tmp/downloaded_data.csv
require 'csv'
data = CSV.read('/tmp/downloaded_data.csv', headers: true)
data.each do |row|
row['email'] = "test_#{row['id']}@example.com" if row['email']
row['phone'] = '0900-000-000' if row['phone']
row['address'] = '測試地址' if row['address']
row['password_digest'] = nil if row['password_digest']
row['token'] = nil if row['token']
end
CSV.open('/tmp/sanitized_data.csv', 'w') do |csv|
csv << data.headers
data.each { |row| csv << row.values_at(*data.headers) }
end
# SQL 匯入
psql -d {db_name} < /tmp/selected_tables.sql
# 或 CSV 匯入
psql -d {db_name} -c "COPY {table} FROM '/tmp/sanitized_data.csv' CSV HEADER"
# 驗證
psql -d {db_name} -c "SELECT count(*) FROM {table};"
# 清理遠端暫存
rm -f /tmp/export_data.rb /tmp/export.csv /tmp/*.sql
適用場景:Staging 要刷新 Production 最新資料,但某些 table 的 staging 測試資料要保留(例如 admin_staffs、users 只存測試帳號的情境)。
優點:不需要 RDS master 權限(不做 DROP DATABASE),app user 即可完成整個流程。
# 在 Staging EC2 上用 pg_dump 備份要保留的 table
PGPASSWORD={stg_password} pg_dump \
-h {stg_rds_host} -U {stg_user} -d {db_name} \
-t {keep_table} --data-only --no-owner --no-acl \
-f /home/apps/{keep_table}_backup_YYYYMMDD.sql
# 驗證備份筆數
PGPASSWORD={stg_password} psql -h {stg_rds_host} -U {stg_user} -d {db_name} \
-c "SELECT count(*) FROM {keep_table};"
💡 多個 table 可重複
-t table1 -t table2一起備份。
⚠️ dump 必須用 pg_dump 16(EC2 上的 9.6 無法 dump PG16 server)。走本地 Docker + SSM tunnel。開始前先
psql -c "SELECT 1;"確認 tunnel 活著。
# 1. 開 prod tunnel(另一個終端 / 背景)
aws ssm start-session --target "{PROD_INSTANCE_ID}" \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["{prod_rds_host}"],"portNumber":["5432"],"localPortNumber":["15440"]}'
# 2. Docker pg16 dump
docker run --rm -e PGPASSWORD={prod_password} -v /tmp:/dump postgres:16 \
pg_dump -h host.docker.internal -p 15440 -U {prod_user} -d {db_name} \
--no-owner --no-acl \
--clean --if-exists \
--exclude-table-data={keep_table} \
--verbose \
-f /dump/{app_name}_prod_YYYYMMDD.sql
# 3. 移除 psql 16 專用 meta-command(舊 psql 9.x 會在 restore 時報錯)
sed -i '' -e '/^\\restrict /d' -e '/^\\unrestrict /d' /tmp/{app_name}_prod_YYYYMMDD.sql
三個關鍵 flag:
--clean --if-exists → dump 內含 DROP TABLE IF EXISTS,restore 時自動清掉舊 table(不需 DROP DATABASE 權限)--exclude-table-data={keep_table} → 保留 schema 但清空資料,restore 後是空表等待 C4 灌入--no-owner --no-acl → 跨 user restore 時避免 owner / grant 衝突⚠️ 不要用本地 Docker + SSM tunnel 做 restore —— SSM tunnel 會在中途 idle 斷線 hang 住;踩過 30+ min 靜默 stuck 的雷。 改走 S3 → EC2 → psql 直連 RDS(VPC 內,穩定)。psql 9.6 對 PG16 做 text restore 相容,前提是 C2 已把
\restrict/\unrestrict刪掉。
# 1. gzip + 上 S3
gzip -cf /tmp/{app_name}_prod_YYYYMMDD.sql > /tmp/{app_name}_prod_YYYYMMDD.sql.gz
aws s3 cp /tmp/{app_name}_prod_YYYYMMDD.sql.gz \
s3://{bucket}/db-backup/{app_name}_prod_YYYYMMDD.sql.gz
# 2. 寫 restore 腳本,用 base64 灌進 SSM(避免 quote 地獄)
cat > /tmp/remote_restore.sh << 'EOF'
#!/bin/bash
set -e
cd /home/apps
aws s3 cp s3://{bucket}/db-backup/{app_name}_prod_YYYYMMDD.sql.gz /home/apps/restore.sql.gz
gunzip -f /home/apps/restore.sql.gz
export PGPASSWORD={stg_password}
export PGHOST={stg_rds_host}
export PGUSER={stg_user}
# 斷掉既有連線(app user 可以終止自己的 session)
psql -d postgres -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname='{db_name}' AND pid<>pg_backend_pid();"
# Restore(--clean 會自動 DROP 再 CREATE 每個 table)
psql -d {db_name} -v ON_ERROR_STOP=0 -f /home/apps/restore.sql \
> /home/apps/restore.stdout 2> /home/apps/restore.stderr
echo "DONE stdout=$(wc -l < /home/apps/restore.stdout) stderr=$(wc -l < /home/apps/restore.stderr)"
rm -f /home/apps/restore.sql
EOF
B64=$(base64 < /tmp/remote_restore.sh | tr -d '\n')
# 3. 用 nohup 背景啟動(避免 SSM send-command timeout,大 DB 時必要)
cat > /tmp/ssm_kick.json <<EOF
{
"commands": [
"echo '$B64' | base64 -d > /home/apps/restore.sh && chmod +x /home/apps/restore.sh",
"sudo -u apps bash -c 'nohup bash /home/apps/restore.sh > /home/apps/restore.log 2>&1 &' && sleep 2 && ps -ef | grep restore.sh | grep -v grep"
]
}
EOF
aws ssm send-command --instance-ids "{STAGING_INSTANCE_ID}" \
--document-name "AWS-RunShellScript" \
--parameters file:///tmp/ssm_kick.json --timeout-seconds 600
# 4. 輪詢進度(每 45 秒,直到 restore.sh process 消失 + log 顯示 DONE)
# 檢查錯誤數(0 最理想;extension-related 錯誤通常可忽略,但要人工 review)
# data-only 備份檔同樣要先 sed 掉 \restrict / \unrestrict
sed -i '' -e '/^\\restrict /d' -e '/^\\unrestrict /d' /tmp/{keep_table}_backup_YYYYMMDD.sql
gzip -cf /tmp/{keep_table}_backup_YYYYMMDD.sql > /tmp/{keep_table}_backup.sql.gz
aws s3 cp /tmp/{keep_table}_backup.sql.gz s3://{bucket}/db-backup/{keep_table}_backup_YYYYMMDD.sql.gz
# 在 EC2 上:下載、gunzip、psql -f 灌回,驗證筆數
# (同 C3 的 base64 + SSM 模式,但操作小,可用單一 send-command 同步跑完)
比對幾個代表性 table 的 count(*),確認 {keep_table} 的筆數等於備份時的筆數,其他 table 等於 production。
rm -f /home/apps/{app_name}_prod_YYYYMMDD.sql
rm -f /home/apps/{keep_table}_backup_YYYYMMDD.sql
# /tmp/*.sh 暫存會被 tmpreaper 清掉,不用手動處理
SSM send-command 的多層引號 escape 非常容易出錯。推薦做法:
方法一:JSON 檔案傳參數(推薦)
# 本地建立 JSON 參數檔
cat > /tmp/ssm-commands.json << 'EOF'
{
"commands": [
"printf '#!/bin/bash\\n...' > /tmp/script.sh",
"chmod +x /tmp/script.sh",
"sudo su - apps -c 'bash /tmp/script.sh 2>&1'"
]
}
EOF
aws ssm send-command --instance-ids "$ID" \
--document-name "AWS-RunShellScript" \
--parameters file:///tmp/ssm-commands.json
方法二:簡單命令可直接用 parameters
aws ssm send-command --instance-ids "$ID" \
--document-name "AWS-RunShellScript" \
--parameters 'commands=["ls -la /home/apps/"]'
方法三(推薦,複雜腳本):base64 encode 把整個 bash 腳本灌進 SSM
避開所有 quote / escape 地獄:本地把 shell script 寫好、base64 編碼、SSM 在遠端 decode 回檔案後執行。
# 1. 本地寫好腳本(想怎麼用 quote 都行,不用 escape)
cat > /tmp/remote.sh << 'EOF'
#!/bin/bash
set -e
echo "hello from $(hostname)"
PGPASSWORD=xxx psql -h rds-host -U user -d db -c "SELECT count(*) FROM tablename;"
EOF
# 2. Base64 編碼
B64=$(base64 < /tmp/remote.sh | tr -d '\n')
# 3. SSM 透過 JSON 檔傳 3 行命令:decode → chmod → 用指定 user 執行
cat > /tmp/ssm.json << EOF
{
"commands": [
"echo '$B64' | base64 -d > /tmp/s.sh && chmod +x /tmp/s.sh",
"sudo -u apps bash /tmp/s.sh 2>&1"
]
}
EOF
aws ssm send-command --instance-ids "$ID" \
--document-name "AWS-RunShellScript" \
--parameters file:///tmp/ssm.json \
--timeout-seconds 600
優點:
'"' / EOF 都不會壞bash /tmp/remote.sh dry-run 更直覺# 送出命令後取得 CommandId
COMMAND_ID=$(aws ssm send-command ... --output text --query "Command.CommandId")
# 等待並取得結果(根據預期時間調整 sleep)
sleep {seconds} && aws ssm get-command-invocation \
--command-id "$COMMAND_ID" \
--instance-id "$INSTANCE_ID" \
--query "[Status, StandardOutputContent, StandardErrorContent]" \
--output text
# 如果 Status 是 InProgress,再等一下重試
❌ 將 Local/Staging 資料推到 Production
❌ 直接在 Production 執行 UPDATE/DELETE
❌ 遷移超過必要範圍的資料(selective 模式)
✅ 遷移前確認需求和範圍
✅ 遷移前檢查磁碟空間
✅ 全庫同步前確認用戶同意覆蓋目標 DB
✅ 遷移後驗證資料完整性
✅ 清理遠端暫存檔案
Production → Local # 建議清理敏感資料
Production → Staging # 同 VPC 內可選擇保留,由用戶決定
1. 確認 staging 能直連 production RDS
2. 檢查磁碟空間,清理舊 dump
3. 在 staging 上 pg_dump production RDS
4. terminate connections → drop → create → restore
5. 驗證 table count
project = Project.find_by(serial: 'RT130044')
export_data = {
project: project.attributes,
invoices: project.invoices.map(&:attributes),
payments: project.payments.map(&:attributes)
}
File.write('/tmp/project_data.json', export_data.to_json)
pg_dump -h {rds_host} -U {user} -d {db_name} --schema-only -f /tmp/schema.sql
遷移完成後輸出:
┌──────────────────────────────────────────────────────┐
│ 📦 資料遷移完成 │
├──────────────────────────────────────────────────────┤
│ 來源:Production RDS ({prod_rds_host}) │
│ 目標:Staging RDS ({staging_rds_host}) │
│ 資料庫:{db_name} │
│ │
│ 📊 遷移統計: │
│ • 資料表數:{table_count} 張 │
│ • Dump 大小:{size} │
│ │
│ ✅ 無錯誤 / ⚠️ 有警告(列出) │
│ ✅ 目標 DB 已完整覆蓋 │
└──────────────────────────────────────────────────────┘