File size: 7,608 Bytes
cd9bca9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# 🔄 PostgreSQL 直連遷移指南
本文件說明如何從 Supabase SDK 遷移到 PostgreSQL 直連的詳細步驟和注意事項。
## 📋 遷移概述
### 變更內容
- ✅ 移除 Supabase Python SDK 依賴
- ✅ 新增 SQLAlchemy + psycopg 直連
- ✅ 重構資料庫服務層
- ✅ 新增 ORM 模型定義
- ✅ 支援 Alembic 資料庫遷移
### 優勢
- 🚀 **更好的效能**: 直連減少中間層開銷
- 🔧 **更多控制**: 完整的 SQL 查詢控制
- 📊 **ORM 支援**: SQLAlchemy 提供強大的 ORM 功能
- 🔄 **遷移管理**: Alembic 提供版本化的資料庫遷移
- 🛡️ **連線池**: 自動連線池管理
## 🔑 環境變數更新
### 舊的 Supabase 設定
```bash
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-key
```
### 新的 PostgreSQL 設定
```bash
DB_HOST=db.your-project.supabase.co
DB_PORT=6543
DB_NAME=postgres
DB_USER=postgres
DB_PASSWORD=your-database-password
```
## 🔍 如何取得 PostgreSQL 連線資訊
### 從 Supabase Dashboard 取得
1. **登入 Supabase Dashboard**
- 前往 [Supabase Dashboard](https://supabase.com/dashboard)
- 選擇您的專案
2. **取得連線資訊**
- 前往 "Settings" → "Database"
- 在 "Connection info" 區域找到:
- **Host**: `db.your-project-ref.supabase.co`
- **Port**: `6543` (PostgreSQL 直連埠)
- **Database**: `postgres`
- **User**: `postgres`
- **Password**: 您設定的資料庫密碼
3. **連線字串範例**
```
postgresql://postgres:your-password@db.your-project-ref.supabase.co:6543/postgres
```
### 從其他 PostgreSQL 提供商取得
如果您使用其他 PostgreSQL 服務:
- **AWS RDS**: 在 RDS Console 中查看端點資訊
- **Google Cloud SQL**: 在 Cloud Console 中查看連線詳情
- **Azure Database**: 在 Azure Portal 中查看連線字串
- **Railway/Render**: 在專案設定中查看資料庫資訊
## 🛠️ 部署步驟
### 1. 更新環境變數
在 Hugging Face Spaces 的 Settings 中更新:
```bash
# 移除舊的 Supabase 設定
# SUPABASE_URL=...
# SUPABASE_KEY=...
# 新增 PostgreSQL 設定
DB_HOST=db.your-project-ref.supabase.co
DB_PORT=6543
DB_NAME=postgres
DB_USER=postgres
DB_PASSWORD=your-database-password
# 其他設定保持不變
LINE_CHANNEL_ACCESS_TOKEN=your-line-token
LINE_CHANNEL_SECRET=your-line-secret
OPENROUTER_API_KEY=your-openrouter-key
OPENROUTER_MODEL=anthropic/claude-3-haiku
```
### 2. 初始化資料庫
部署後,執行資料庫初始化:
```bash
# 在容器中執行
python -m backend.database.init_db
```
或者透過 API 端點觸發初始化(如果實作了相關端點)。
### 3. 驗證連線
檢查健康檢查端點:
```bash
curl https://your-space-url.hf.space/health
```
應該會看到:
```json
{
"status": "healthy",
"message": "LINE Bot API is operational",
"database": "connected",
"database_url": "postgresql://your-host:6543/postgres"
}
```
## 📊 資料庫模型對應
### 新的 SQLAlchemy 模型
```python
# backend/database/models.py
class User(Base):
__tablename__ = "users"
user_id = Column(String(255), primary_key=True)
name = Column(String(255))
email = Column(String(255))
# ... 其他欄位
class Product(Base):
__tablename__ = "products"
product_id = Column(Integer, primary_key=True)
name = Column(String(255), nullable=False)
price = Column(DECIMAL(10, 2), nullable=False)
# ... 其他欄位
```
### 資料表關聯
```python
# 一對多關聯
class User(Base):
orders = relationship("Order", back_populates="user")
class Order(Base):
user = relationship("User", back_populates="orders")
order_items = relationship("OrderItem", back_populates="order")
```
## 🔄 API 變更
### 查詢方式變更
#### 舊的 Supabase 方式
```python
result = supabase.table("users").select("*").eq("name", "張三").execute()
```
#### 新的 SQLAlchemy 方式
```python
db = get_database_session()
users = db.query(User).filter(User.name == "張三").all()
```
### 錯誤處理改進
```python
def database_operation():
db = None
try:
db = get_database_session()
# 資料庫操作
result = db.query(User).all()
db.commit()
return result
except Exception as e:
if db:
db.rollback()
logger.error(f"資料庫操作失敗: {str(e)}")
raise
finally:
if db:
close_database_session(db)
```
## 🚀 效能優化
### 連線池設定
```python
# backend/database/connection.py
engine = create_engine(
settings.DATABASE_URL,
pool_size=10, # 連線池大小
max_overflow=20, # 最大溢出連線
pool_pre_ping=True, # 連線前檢查
pool_recycle=3600, # 1小時後回收連線
)
```
### 查詢優化
```python
# 使用 eager loading 避免 N+1 查詢
from sqlalchemy.orm import joinedload
users_with_orders = db.query(User).options(
joinedload(User.orders)
).all()
# 使用索引優化查詢
# 在模型中定義索引
class User(Base):
__tablename__ = "users"
name = Column(String(255), index=True) # 建立索引
```
## 🔧 開發工具
### Alembic 遷移
```bash
# 初始化 Alembic
alembic init alembic
# 建立遷移檔案
alembic revision --autogenerate -m "Initial migration"
# 執行遷移
alembic upgrade head
# 回滾遷移
alembic downgrade -1
```
### 本地開發
```bash
# 安裝依賴
pip install -r requirements.txt
# 設定環境變數
export DB_HOST=localhost
export DB_PORT=5432
export DB_NAME=linebot_dev
export DB_USER=postgres
export DB_PASSWORD=password
# 初始化資料庫
python -m backend.database.init_db
# 執行應用程式
uvicorn backend.main:app --reload --port 7860
```
## 🛡️ 安全性考量
### 連線安全
1. **使用 SSL 連線**
```python
DATABASE_URL = f"postgresql+psycopg://{user}:{password}@{host}:{port}/{db}?sslmode=require"
```
2. **限制資料庫權限**
- 建立專用的應用程式使用者
- 只授予必要的資料表權限
- 定期輪換密碼
3. **連線字串保護**
- 使用環境變數儲存敏感資訊
- 避免在日誌中記錄連線字串
- 使用密碼管理工具
## 📈 監控與除錯
### 日誌設定
```python
# 啟用 SQLAlchemy 日誌
engine = create_engine(
settings.DATABASE_URL,
echo=settings.DEBUG, # 在 DEBUG 模式下顯示 SQL
)
```
### 效能監控
```python
import time
from functools import wraps
def monitor_db_performance(func):
@wraps(func)
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
execution_time = time.time() - start_time
logger.info(f"{func.__name__} 執行時間: {execution_time:.2f}秒")
return result
return wrapper
```
## 🚨 常見問題
### Q: 連線失敗怎麼辦?
A: 檢查以下項目:
1. 主機名稱和埠號是否正確
2. 使用者名稱和密碼是否正確
3. 資料庫是否允許外部連線
4. 防火牆設定是否正確
### Q: 效能比 Supabase SDK 慢?
A: 可能原因:
1. 連線池設定不當
2. 查詢未優化
3. 缺少適當的索引
4. 網路延遲問題
### Q: 如何處理資料庫遷移?
A: 使用 Alembic:
1. 建立遷移腳本
2. 在部署前測試遷移
3. 備份資料庫
4. 執行遷移
## 📞 技術支援
如果遇到問題:
1. 檢查應用程式日誌
2. 驗證環境變數設定
3. 測試資料庫連線
4. 參考 SQLAlchemy 官方文件
---
**注意**: 遷移前請務必備份您的資料庫,並在測試環境中驗證所有功能正常運作。 |