Files
go-omni/database/README.md

129 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# database
结构化 MySQL 配置、独立 TLS/mTLS、驱动日志和生成项目接入见 [官方 MySQL 适配器](mysql/README.md)。已有 Open/OpenConnector 接口继续支持。
使用 GORM 的项目可显式接入 [gormx 可选适配器](gormx/README.md),复用本包连接池,并将 SQL 日志接入 logx;普通 database 包不导入 GORM。
`database` 包提供基于标准库 `database/sql` 的连接池生命周期,不绑定 ORM 或驱动:
- `Config` / `ConfigFromEnv`:连接池参数和 `GO_OMNI_DB_*` 环境变量。
- `Open` / `OpenConnector`:通过 DSN 或标准 Connector 创建连接池、设置连接上限并在返回前执行 `PingContext`。
- `Health`:用于就绪检查,等待连接和 Ping 均受 `PingTimeout` 限制。
- `InTx`:统一事务提交和回滚;工作函数返回错误或 panic 时回滚。
- `Close`:由嵌入的 `*sql.DB` 提供,应用退出时显式调用。
框架不导入 MySQL、PostgreSQL 等具体驱动。应用负责注册驱动:
```go
import (
"context"
_ "github.com/go-sql-driver/mysql"
"git.yuntuo.hk/k2safe/go-omni/database"
)
cfg, err := database.ConfigFromEnv("GO_OMNI_DB_")
if err != nil {
return err
}
db, err := database.Open(context.Background(), cfg)
if err != nil {
return err
}
defer db.Close()
```
连接池相关环境变量:
```text
GO_OMNI_DB_DRIVER=mysql
GO_OMNI_DB_DSN=user:password@tcp(127.0.0.1:3306)/app?parseTime=true
GO_OMNI_DB_MAX_OPEN_CONNS=10
GO_OMNI_DB_MAX_IDLE_CONNS=5
GO_OMNI_DB_CONN_MAX_LIFETIME=30m
GO_OMNI_DB_CONN_MAX_IDLE_TIME=5m
GO_OMNI_DB_PING_TIMEOUT=5s
```
使用 `ConfigFromEnv` / `Open` 时 `DSN` 必填,环境变量入口的驱动默认是 `mysql`。数据库建库、迁移、表结构和具体 Repository 属于业务项目或可选模块,不会被核心包自动执行。
`MaxIdleConns=0` 会禁用空闲连接。初始化 Ping 失败会关闭已创建的连接池。
`go-omni new --database mysql` 会生成项目自己的 MySQL Repository、ServiceContext、
数据库就绪探针和 `schema.sql`。核心包不需要知道业务表结构。
真实数据库验收(需要本地 Docker):
```sh
python3 scripts/verifyDatabase.py --version v0.2.0
```
脚本仅操作本次创建的独立容器与数据库,验证 HTTP CRUD、服务重启持久化、事务提交与
错误/panic/取消回滚、连接池关闭、缺少表结构时启动失败,以及停库后的 readiness 503 和恢复后的 200。
结束时清理容器、匿名数据卷和临时项目。常规 `go test ./...` 不依赖 Docker。
## 项目配置叠加
`database.ApplyEnv(cfg, prefix)` 在已有文件/默认配置上覆盖非空环境变量,保留未覆盖的池参数。
`Config` 的 JSON/YAML 字段使用 lowerCamelCase,`DSN` 使用 `json:"-"`,连接密钥从环境变量加载。
API 脚手架 `--database mysql` 使用此流程,并要求正的 `maxOpenConns`,提供数据库 readiness 与幂等清理。
具体表结构、迁移和 Repository 留在业务项目,参考 `examples/userService`。
## Connector 接入(v0.9.1-preview)
项目已有 `database/sql/driver.Connector` 时使用 `OpenConnector`。这是标准驱动接口,核心包不增加具体驱动依赖。项目可以在同一进程创建多个使用不同证书、日志、拨号策略的连接池。
下面是 MySQL 的完整组装函数;连接地址、凭据、TLS 和驱动 Logger 都从调用方传入,不在框架中约定:
```go
package connection
import (
"context"
"crypto/tls"
"github.com/go-sql-driver/mysql"
"git.yuntuo.hk/k2safe/go-omni/database"
)
func Open(ctx context.Context, address, user, password, name string,
tlsConfig *tls.Config, logger mysql.Logger,
pool database.PoolConfig) (*database.DB, error) {
cfg := mysql.NewConfig()
cfg.Net, cfg.Addr = "tcp", address
cfg.User, cfg.Passwd, cfg.DBName = user, password, name
cfg.TLS = tlsConfig // 项目设置 RootCAs、ServerName、MinVersion 等
if logger != nil {
cfg.Logger = logger // 项目现有的 Print(...any) 日志适配器
}
connector, err := mysql.NewConnector(cfg)
if err != nil {
return nil, err
}
return database.OpenConnector(ctx, connector, pool)
}
```
调用时以 `database.DefaultPoolConfig()` 为起点,按项目需要调整。已有 `database.Config` 可调用 `.PoolConfig()` 提取池设置;`ConfigFromEnv` / `ApplyEnv` 仍是 DSN 入口,不用为 Connector 填假 DSN。`PoolConfig` 支持通过 `config.DecodeFile` 加载项目的 JSON/YAML 嵌套配置,环境覆盖由项目按自己的驱动配置组织。
| PoolConfig 字段 | 默认值 / 含义 |
| --- | --- |
| `MaxOpenConns` | `10`;`0` 表示不限制 |
| `MaxIdleConns` | `5`;`0` 禁止保留空闲连接 |
| `ConnMaxLifetime` | `30m`;`0` 不因连接年龄回收 |
| `ConnMaxIdleTime` | `5m`;`0` 不因空闲时长回收 |
| `PingTimeout` | `5s`;必须为正,约束启动 Ping 和 Health 等待 |
返回的 `*database.DB` 嵌入 `*sql.DB`,可使用 `QueryContext`、`ExecContext`、`Stats`,以及框架的 `Health`、`InTx`。需要标准数据库指针的 ORM/迁移器可取 `db.DB`;不要重复建立池。项目负责驱动支持的 context 取消与读写超时设置,框架不能强制中断不遵守 context 的自定义驱动。
**生命周期:** nil/带类型的 nil Connector、非法池参数、启动前已取消的 context 会在创建池前返回,Connector 仍归调用方。进入 `sql.OpenDB` 后由池持有;启动 Ping 失败自动关闭,成功后由调用方负责 `db.Close`,通常注册 `app.OnShutdown(db.Close)`。若 Connector 实现 `io.Closer`,遵循标准 `database/sql` 规则随池关闭;有资源的 Connector 不应跨多个池共享。资源初始化过程中、注册退出回调之前若业务校验失败,项目也须关闭池。
`db.PoolConfig()` 返回池配置快照。Connector 入口的 `db.Config()` 中 `Driver` / `DSN` 为空,不能用它重建 Connector。TLS、Logger、驱动版本检查、字符集、时区以及迁移规则保持由项目负责;不写入框架配置快照。
验收脚本使用独立本地 MySQL 8.4 容器(1 CPU / 768 MiB),自动生成测试 CA/证书与随机凭据,检查 TLS 信任/主机名、两池配置隔离、驱动日志、事务和 HTTP 超时,结束后清理本次资源:
```sh
python3 scripts/verifyConnector.py --local --report performance/connectorLocal.json
# 发布后通过全新 module cache 验证远程依赖,无本地 replace:
python3 scripts/verifyConnector.py --version v0.9.1-preview --report performance/connectorRemote.json
```