# 数据库配置与初始化说明（PostgreSQL / Redis）

> 记录平台的 **PostgreSQL 账号密码**、**Redis 账号密码**、**数据库地址在代码中的配置位置**，
> 以及**切换 PG 数据集时如何执行完整初始化 SQL**。

---

## 1. 账号密码速查表

### 1.1 PostgreSQL

| 环境 | 地址 | 用户 | 密码 | 数据库 | 来源 |
|------|------|------|------|--------|------|
| 代码默认值 | `localhost:15432` | `yg_ft` | `change_me` | `yg_ft` | `config.py` / `session.py` 的 `DATABASE_URL` 兜底 |
| Docker 部署 | `www.caoxiaozhu.com:5432` | `root` | `8811614287327Leo` | `yg_ft` | `docker/app/.env` 的 `DATABASE_URL` |
| Docker 内置 Postgres（已注释） | `localhost:15432` | `root` | `8811614287327Leo` | `yg_ft` | `docker/app/docker-compose.yml` 注释掉的 postgres 服务 |

> ⚠️ `change_me` 与 `8811614287327Leo` 均为默认/示例凭据，生产环境务必更换。

### 1.2 Redis

| 项 | 值 | 说明 |
|----|-----|------|
| 连接串 | `redis://:<REDIS_PASSWORD>@redis:6379/0` | 已内嵌密码；docker 网络内服务名 `redis`，端口 6379，db 0 |
| 对外端口 | `16379`（`REDIS_PORT`） | 宿主机映射 |
| 密码 | `docker/app/.env` 的 `REDIS_PASSWORD` | 已启用 `requirepass` 鉴权 |
| 镜像 | `redis:7-alpine` | 已开启 AOF（`--appendonly yes`）+ `requirepass` |

> **当前后端代码未使用 Redis**：`redis` 包已列入 `requirements.txt`，`REDIS_URL` 通过
> docker-compose 注入容器，但全仓库 `backend/`、`compute/` 没有任何 `import redis` /
> `Redis(...)` 连接代码。Redis 为后续功能预留；**即便如此仍已配置鉴权**，
> 避免无密码实例对外暴露（纵深防御）。未来启用时按 `REDIS_URL` 连接即可。
>
> 健康检查通过容器环境变量 `REDISCLI_AUTH` 认证，不在进程参数中泄露密码。

---

## 2. 数据库地址在代码中的配置位置

### 2.1 后端（backend）

| 文件 | 作用 | 取值 |
|------|------|------|
| `backend/app/core/config.py` | **唯一权威配置**，`Settings.database_url` | `os.getenv("DATABASE_URL", "postgresql+psycopg://yg_ft:change_me@localhost:15432/yg_ft")` |
| `backend/app/db/session.py` | SQLAlchemy 引擎（`get_db` / `session_scope`） | `os.getenv("DATABASE_URL", ...)` 同样兜底 |
| `backend/app/db/platform_store.py` | **平台主存储**，直接用 psycopg 连接池 | 取 `settings.database_url`，`_psycopg_url()` 把 `postgresql+psycopg://` 转成 `postgresql://` |
| `backend/app/modules/data_process/store.py` | 数据处理存储 | `get_settings().database_url` |

> **环境变量加载顺序**：`config.py` 导入时会 `load_dotenv(backend/.env, override=True)`，
> 即 **`backend/.env` 会覆盖系统环境变量**；docker 部署则直接由 compose 注入 `DATABASE_URL`。
> 最终优先级：`backend/.env` / compose 注入的环境变量 > 代码内默认值。

### 2.2 部署配置（docker）

| 文件 | 关键项 |
|------|--------|
| `docker/app/.env` | `DATABASE_URL`、`POSTGRES_USER`、`POSTGRES_PASSWORD`、`REDIS_URL`、`REDIS_PORT` |
| `docker/app/docker-compose.yml` | `backend-api` 环境透传上述变量；`redis` 服务定义 |

```ini
# docker/app/.env（节选）
DATABASE_URL=postgresql+psycopg://root:8811614287327Leo@www.caoxiaozhu.com:5432/yg_ft
POSTGRES_USER=root
POSTGRES_PASSWORD=8811614287327Leo
REDIS_PASSWORD=<强密码>                    # Redis requirepass（新增鉴权）
REDIS_URL=redis://:<REDIS_PASSWORD>@redis:6379/0   # 连接串内嵌密码
REDIS_PORT=16379
USE_BUILTIN_POSTGRES=false   # 当前用共享外部库，内置 postgres 服务被注释
USE_BUILTIN_REDIS=true       # Redis 用内置服务
```

---

## 3. 完整初始化 SQL

### 3.1 脚本位置

| 脚本 | 用途 |
|------|------|
| **`backend/app/db/sql/000_full_init.sql`** | **一键初始化脚本（新增）**：建库表 + 索引 + 种子数据，幂等，覆盖全部 39 张运行表 |
| `backend/app/db/sql/001_platform_runtime.sql` | 平台核心表（应用启动自动执行） |
| `backend/app/db/sql/002_governance.sql` | 治理表（应用启动自动执行） |
| `backend/app/db/sql/003_tenant_quota.sql` | 租户配额列（应用启动自动执行） |
| `backend/app/db/sql/003_model_path_governance.sql` | 模型可训练列（**应用不自动执行**，已并入完整脚本） |
| `backend/app/db/sql/002_data_process.sql` | 数据处理表（**应用不自动执行**，已并入完整脚本） |
| `docs/postgres-schema.sql` | ⚠️ **目标设计稿**（UUID/JSONB），与运行时代码不兼容，**不要用于初始化** |

> **重要**：`docs/postgres-schema.sql` 是规划中的“目标 schema”（UUID 主键、`ft_platform` schema 等），
> 运行时代码明确拒绝该结构（`002_data_process.sql` 检测到 `datasets.id` 非 TEXT 会直接报错）。
> 初始化请使用 **`000_full_init.sql`**。

### 3.2 执行步骤（全新 PG 环境）

**第 1 步：创建角色与数据库**（必须单独执行，不能放进事务）

```sql
-- 以超级用户（如 postgres）连接：
CREATE ROLE  yg_ft LOGIN PASSWORD '请改为强密码';
CREATE DATABASE yg_ft OWNER yg_ft;
-- 如需应用执行 CREATE EXTENSION 等，可再授予超级用户（按需）：
-- ALTER ROLE yg_ft SUPERUSER;
```

**第 2 步：执行完整初始化脚本**

```bash
psql "postgresql://yg_ft:密码@<host>:5432/yg_ft" \
     -f backend/app/db/sql/000_full_init.sql
```

脚本特点：
- 全程一个事务（`BEGIN; ... COMMIT;`），失败自动回滚
- 所有 DDL 使用 `IF NOT EXISTS` / `ADD COLUMN IF NOT EXISTS`，**可重复执行**
- 含 `DO $$...$$` 语句块，必须用 `psql` 执行（应用内部的按分号切分 `executescript()` 不适用）
- 自动写入种子用户：`admin / admin123`、`operator / operator123`（登录后请改密）

**第 3 步：校验**

```sql
SELECT count(*) FROM pg_tables WHERE schemaname = 'public';          -- 应 ≥ 39
SELECT username, role, status FROM users;                            -- 应有 admin / operator
```

### 3.3 执行方式对比（三种途径）

| 方式 | 覆盖范围 | 命令 |
|------|----------|------|
| **A. 完整脚本（推荐，切换新库）** | 全部 39 表 + 索引 + 种子 | `psql ... -f 000_full_init.sql` |
| B. 应用自动初始化 | 001 + 002_governance + 003_tenant_quota + 种子用户；**不含**数据处理表、`models.can_train`、`data_convert_tasks` | 应用首次调用 `get_platform_store()` 时 `ensure_schema()` 自动执行 |
| C. 数据处理表单独安装 | `002_data_process.sql` 全部内容 | 在 `backend/` 目录下：`python -m app.modules.data_process.schema_cli --apply --yes`（或 `--check` 只读检查） |

> **缺口说明**：
> - `models.can_train`（训练预检用）只在 `003_model_path_governance.sql` 中创建，应用启动**不会**自动执行；
> - `data_convert_tasks`（数据转换任务表）运行时代码引用但**原 SQL 脚本缺失**；
>   已统一并入 `000_full_init.sql` 补齐。若现有库缺这两项，执行一次完整脚本即可幂等补上。

### 3.4 完整脚本包含的表（39 张）

**核心**：users、models、trained_models、model_lineage、model_artifacts、model_export_jobs、
datasets、dataset_files、compute_nodes、gpus、fine_tune_tasks、fine_tune_metrics、
fine_tune_checkpoints、compute_jobs、gpu_allocations、scheduler_locks、resource_replicas、
resource_sync_jobs、eval_tasks、eval_dimensions、compare_tasks、projects、project_members、
roles、sessions、acls

**治理**：tenants、approval_templates、approval_instances、approval_steps、audit_logs、retention_policies

**数据处理**：data_process_tasks、data_process_source_files、data_process_preview_items、
data_process_results、dataset_file_versions、dataset_records

**数据转换**：data_convert_tasks（新增补齐）

---

## 4. 安全注意事项

1. **更换默认密码**：`change_me`（代码兜底）、`8811614287327Leo`（部署）、`admin123`/`operator123`（种子用户）、`REDIS_PASSWORD` 上线前必须更换。
2. **Redis 已加鉴权**：已配置 `requirepass` + `REDISCLI_AUTH` 健康检查；`REDIS_URL` 内嵌密码。若端口需暴露公网，仍建议用防火墙/安全组限制来源。
3. **`docker/*/.env` 已入库，含明文凭据**：
   - `backend/.env` 已被 `.gitignore` 排除；
   - 但 `docker/app/.env`、`docker/compute/.env` 目前被 git 跟踪（`git ls-files` 可见），
     其中的 `DATABASE_URL`、`POSTGRES_PASSWORD`、`COMPUTE_SERVICE_TOKEN` 等均为明文。
   - **建议**：轮换这些凭据，将 `docker/*/.env` 移出版本库（`git rm --cached`）并改用
     部署侧机密注入（如 docker secrets / CI 变量 / 环境变量模板），保留 `.env.example` 作为模板。
4. **最小权限**：应用角色只需对业务库的 DML/DDL 权限，尽量避免 SUPERUSER。
