MySQL **不支援** RENAME DATABASE(5.1.7 短暫存在後移除,因可能導致資料遺失)。資料庫重命名本質是「建新庫 → 移動表 → 刪舊庫」。
-- 前提:新資料庫已存在
CREATE DATABASE new_db;
-- 逐表重命名(可批量生成 SQL)
RENAME TABLE
old_db.table1 TO new_db.table1,
old_db.table2 TO new_db.table2,
old_db.table3 TO new_db.table3;
-- 驗證後刪除舊庫
DROP DATABASE old_db;
優點:單條語句原子操作、無鎖表(元數據鎖極短)、保留所有索引/外鍵/觸發器/權限。
缺點:表多時 SQL 較長,需腳本生成。
# 1. 導出(單線程,大表慢)
mysqldump -u root -p --single-transaction --routines --triggers --events old_db | gzip > old_db.sql.gz
# 2. 建新庫
mysql -u root -p -e "CREATE DATABASE new_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;"
# 3. 導入
gunzip < old_db.sql.gz | mysql -u root -p new_db
# 4. 驗證無誤後刪舊庫
mysql -u root -p -e "DROP DATABASE old_db;"
優點:支援跨版本、跨引擎、可壓縮傳輸、邏輯備份可審計。
缺點:大庫耗時長、需額外磁盤空間、導入時鎖表(視引擎)。
# 1. 停止 MySQL
net stop MySQL80
# 2. 重命名 data 目錄下的資料庫資料夾
rename "C:\ProgramData\MySQL\MySQL Server 8.0\Data\old_db" "new_db"
# 3. 啟動 MySQL
net start MySQL80
⚠ 極高風險:InnoDB 共享表空間 ibdata1 存有數據字典,**絕不可用於 InnoDB 表**。僅適用純 MyISAM 歷史庫。
#!/bin/bash
# rename_db.sh old_db new_db
OLD=$1; NEW=$2
MYSQL="mysql -u root -p'pass' -N -s"
$MYSQL -e "CREATE DATABASE IF NOT EXISTS \`$NEW\`;"
TABLES=$($MYSQL -e "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='$OLD'")
for t in $TABLES; do
$MYSQL -e "RENAME TABLE \`$OLD\`.\`$t\` TO \`$NEW\`.\`$t\`;"
done
# $MYSQL -e "DROP DATABASE \`$OLD\`;"
echo "完成:$OLD -> $NEW (舊庫未刪除,請驗證後手動刪除)"
| 項目 | 影響 | 應對 |
|---|---|---|
| 視圖 | RENAME TABLE 可移動視圖 | 正常處理 |
| 存儲過程/函數/觸發器 | 定義中硬編碼資料庫名會失效 | 避免在程式碼中寫死 DB 名,或導出後 sed 替換 |
| 外鍵關聯 | 同庫內 FK 自動更新;跨庫 FK 需手動調整 | 檢查 information_schema.REFERENTIAL_CONSTRAINTS |
| 權限 | 庫級權限不隨表移動 | 重新授予新庫權限 |
| Binlog 複製 | RENAME TABLE 會記錄到 Binlog,從庫同步執行 |
SELECT CONCAT('RENAME TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` TO `new_db`.`', TABLE_NAME, '`;')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'old_db';
首選 RENAME TABLE(方法一/四)**:原子、在線、零資料拷貝、保留所有物件屬性。大表、跨實例、需壓縮傳輸時用 mysqldump。嚴禁對 InnoDB 直接改目錄名。操作前必須備份、驗證腳本、規劃回滾、非高峰執行、事後驗證行數與應用連通性。