- Created by 郭强, last modified by 糖水不加糖 on Feb 01, 2023
配置文件
我们推荐使用配置组件来管理数据库配置,并使用g
对象管理模块中的g.DB("数据库分组名称")
方法获取数据库操作对象,数据库对象将会自动读取配置组件中的相应配置项,并自动初始化该数据库操作的单例对象。数据库配置管理功能使用的是配置管理组件实现(配置组件采用接口化设计默认使用文件系统实现),同样支持多种数据格式如:toml/yaml/json/xml/ini/properties
。默认并且推荐的配置文件数据格式为yaml
。
简单配置
一个简单的数据库配置如下:
database: default: type: "mysql" link: "root:12345678@tcp(127.0.0.1:3306)/test" user: type: "mysql" link: "root:12345678@tcp(127.0.0.1:3306)/user"
以上数据库配置示例中包含两个数据库分组default
和user
,在代码中可以通过g.DB()
和g.DB("user")
获取对应的数据库连接对象。也可以将type
数据库类型写到link
配置项中,以上简化为:
database: default: link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" user: link: "mysql:root:12345678@tcp(127.0.0.1:3306)/user"
不同数据类型对应的link
如下:
类型 | link配置 | 更多参数 |
---|---|---|
mysql | mysql: 账号:密码@tcp(地址:端口)/数据库名称 | mysql |
mariadb | mariadb: 账号:密码@tcp(地址:端口)/数据库名称 | mysql |
tidb | mtidb: 账号:密码@tcp(地址:端口)/数据库名称 | mysql |
pgsql | pgsql: user=账号 password=密码 host=地址 port=端口 dbname=数据库名称 | pq |
mssql | mssql: user id=账号;password=密码;server=地址;port=端口;database=数据库名称;encrypt=disable | go-mssqldb |
sqlite | sqlite: 文件绝对路径 (如: /var/lib/db.sqlite3 ) | go-sqlite3 |
oracle | oracle://账号:密码@地址:端口/数据库名称 | go-oci8 |
各数据库类型更详细的link
参数信息请查看对应引擎官网,支持的数据库类型参考 数据库ORM 章节。
完整配置
完整的config.yaml
数据库配置项的数据格式形如下:
database: 分组名称: host: "地址" port: "端口" user: "账号" pass: "密码" name: "数据库名称" type: "数据库类型(mysql/pgsql/mssql/sqlite/oracle)" link: "(可选)自定义数据库链接信息,当该字段被设置值时,以上链接字段(Host,Port,User,Pass,Name)将失效,但是type必须有值" role: "(可选)数据库主从角色(master/slave),不使用应用层的主从机制请均设置为master" debug: "(可选)开启调试模式" prefix: "(可选)表名前缀" dryRun: "(可选)ORM空跑(只读不写)" charset: "(可选)数据库编码(如: utf8/gbk/gb2312),一般设置为utf8" weight: "(可选)负载均衡权重,用于负载均衡控制,不使用应用层的负载均衡机制请置空" timezone: "(可选)时区配置,例如:local,Asia/Shanghai" maxIdle: "(可选)连接池最大闲置的连接数" maxOpen: "(可选)连接池最大打开的连接数" maxLifetime: "(可选)连接对象可重复使用的时间长度" createdAt: "(可选)自动创建时间字段名称" updatedAt: "(可选)自动更新时间字段名称" deletedAt: "(可选)软删除时间字段名称" timeMaintainDisabled: "(可选)是否完全关闭时间更新特性,true时CreatedAt/UpdatedAt/DeletedAt都将失效"
完整的数据库配置项示例(YAML
):
database: default: host: "127.0.0.1" port: "3306" user: "root" pass: "12345678" name: "test" type: "mysql" role: "master" debug: "true" dryrun: 0 weight: "100" prefix: "gf_" charset: "utf8" timezone: "local" maxIdle: "10" maxOpen: "100" maxLifetime: "30s"
使用该配置方式时,为保证数据库安全,默认底层不支持多行SQL
语句执行。为了得到更多配置项控制,请参考推荐的简化配置,同时建议您务必了解清楚简化配置项中每个连接参数的功能作用。
集群模式
gdb
的配置支持集群模式,数据库配置中每一项分组配置均可以是多个节点,支持负载均衡权重策略,例如:
database: default: - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" role: "master" - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test" role: "slave" user: - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/user" role: "master" - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/user" role: "slave" - link: "mysql:root:12345678@tcp(127.0.0.1:3306)/user" role: "slave"
以上数据库配置示例中包含两个数据库分组default
和user
,其中default
分组包含一主一从,user
分组包含一主两从。在代码中可以通过g.DB()
和g.DB("user")
获取对应的数据库连接对象。
日志配置
gdb
支持日志输出,内部使用的是glog.Logger
对象实现日志管理,并且可以通过配置文件对日志对象进行配置。默认情况下gdb
关闭了DEBUG
日志输出,如果需要打开DEBUG
信息需要将数据库的debug
参数设置为true
。以下是为一个配置文件示例:
database: logger: path: "/var/log/gf-app/sql" level: "all" stdout: true default: link: "mysql:root:12345678@tcp(127.0.0.1:3306)/user_center" debug: true
其中database.logger
即为gdb
的日志配置,当该配置不存在时,将会使用日志组件的默认配置,具体请参考 日志组件-配置管理 章节。
需要注意哦:由于ORM
底层都是采用安全的预处理执行方式,提交到底层的SQL
与参数其实是分开的,因此日志中记录的完整SQL
仅作参考方便人工阅读,并不是真正提交到底层的SQL
语句。
原生配置(高阶,可选)
以下为数据库底层管理配置介绍,如果您对数据库的底层配置管理比较感兴趣,可继续阅读后续章节。
数据结构
gdb
数据库管理模块的内部配置管理数据结构如下:
ConfigNode
用于存储一个数据库节点信息;ConfigGroup
用于管理多个数据库节点组成的配置分组(一般一个分组对应一个业务数据库集群);Config
用于管理多个ConfigGroup
配置分组。
配置管理特点:
- 支持多节点数据库集群管理;
- 每个节点可以单独配置连接属性;
- 采用单例模式管理数据库实例化对象;
- 支持对数据库集群分组管理,按照分组名称获取实例化的数据库操作对象;
- 支持多种关系型数据库管理,可通过
ConfigNode.Type
属性进行配置; - 支持
Master-Slave
读写分离,可通过ConfigNode.Role
属性进行配置; - 支持客户端的负载均衡管理,可通过
ConfigNode.Weight
属性进行配置,值越大,优先级越高;
type Config map[string]ConfigGroup // 数据库配置对象 type ConfigGroup []ConfigNode // 数据库分组配置 // 数据库配置项(一个分组配置对应多个配置项) type ConfigNode struct { Host string // 地址 Port string // 端口 User string // 账号 Pass string // 密码 Name string // 数据库名称 Type string // 数据库类型:mysql, sqlite, mssql, pgsql, oracle Link string // (可选)自定义链接信息,当该字段被设置值时,以上链接字段(Host,Port,User,Pass,Name)将失效(该字段是一个扩展功能) Role string // (可选,默认为master)数据库的角色,用于主从操作分离,至少需要有一个master,参数值:master, slave Debug bool // (可选)开启调试模式 Charset string // (可选,默认为 utf8)编码,默认为 utf8 Prefix string // (可选)表名前缀 Weight int // (可选)用于负载均衡的权重计算,当集群中只有一个节点时,权重没有任何意义 MaxIdleConnCount int // (可选)连接池最大闲置的连接数 MaxOpenConnCount int // (可选)连接池最大打开的连接数 MaxConnLifetime time.Duration // (可选,单位秒)连接对象可重复使用的时间长度 }
特别说明,gdb
的配置管理最大的特点是,(同一进程中)所有的数据库集群信息都使用同一个配置管理模块进行统一维护,不同业务的数据库集群配置使用不同的分组名称进行配置和获取。
配置方法
这是原生调用gdb
模块来配置管理数据库。如果开发者想要自行控制数据库配置管理可以参考以下方法。若无需要可忽略该章节。
接口文档: https://pkg.go.dev/github.com/gogf/gf/v2/database/gdb
// 添加一个数据库节点到指定的分组中 func AddConfigNode(group string, node ConfigNode) // 添加一个配置分组到数据库配置管理中(同名覆盖) func AddConfigGroup(group string, nodes ConfigGroup) // 添加一个数据库节点到默认的分组中(默认为default,可修改) func AddDefaultConfigNode(node ConfigNode) // 添加一个配置分组到数据库配置管理中(默认分组为default,可修改) func AddDefaultConfigGroup(nodes ConfigGroup) // 设置默认的分组名称,获取默认数据库对象时将会自动读取该分组配置 func SetDefaultGroup(groupName string) // 设置数据库配置为定义的配置信息,会将原有配置覆盖 func SetConfig(c Config)
默认分组表示,如果获取数据库对象时不指定配置分组名称,那么gdb
默认读取的配置分组。例如:gdb.NewByGroup()
可获取一个默认分组的数据库对象。简单的做法,我们可以通过gdb
包的SetConfig
配置管理方法进行自定义的数据库全局配置,例如:
gdb.SetConfig(gdb.Config { "default" : gdb.ConfigGroup { gdb.ConfigNode { Host : "192.168.1.100", Port : "3306", User : "root", Pass : "123456", Name : "test", Type : "mysql", Role : "master", Weight : 100, }, gdb.ConfigNode { Host : "192.168.1.101", Port : "3306", User : "root", Pass : "123456", Name : "test", Type : "mysql", Role : "slave", Weight : 100, }, }, "user-center" : gdb.ConfigGroup { gdb.ConfigNode { Host : "192.168.1.110", Port : "3306", User : "root", Pass : "123456", Name : "test", Type : "mysql", Role : "master", Weight : 100, }, }, })
随后,我们可以使用gdb.NewByGroup("数据库分组名称")
来获取一个数据库操作对象。该对象用于后续的数据库一系列方法/链式操作。
- No labels
39 Comments
roy
哈咯,关于日志我想咨询一下
我这边有这样的需求,全量格式化
json
日志输出,并保留之前的输出方法api
。通过源码翻看,
DB
对象是有SetLogger
的方法,但是是个glog
的struct
。这里是否能考虑改成interface
呢?通过接口外放自定义输出能力。Tian Gilbert
oracle
的配置能不能增加一个比较详细的示例啊?wenzi
config.toml
中使用上面的配置。例如tnsnames.ora
如下其中
name
是配置在监听文件中的的监听的名字。例如数据库的sid
是orclsid
,那么config.toml
中的name
就是orcl
。另外,部署环境时建议直接安装
oracle
客户端,不要按照网上的下载单独的SDK
,虽然SDK
比较小,但是太麻烦,直接装客户端比较简单。Topman
sqlite
该在gf-cli
工具中如何配置?目前使用的数据库配置如下:gf-cli
工具已经按照文档打开go-sqlite
注释并编译,但具体到使用上面工程配置时,使用gf den dao
一直报配置错误。郭强
工具配置参考章节:数据规范-gen dao
Jameszyq
使用
db.model.one
去查询的时候,返回的错误对象中提示NextBytes InitializeSecurityContext failed 8009030e
请问这个是什么问题呢?也没有返回数据Jameszyq
找到问题啦,是数据库配置文件哪里,多加了一个type的字段
如果这样配置,就会出问题:
这样就不会:
可是教程上不是可以这么配置吗?
难道是数据库不同的问题吗?
这个数据库是
sqlserver
郭强
ORM
组件需要识别你配置的数据库类型,你可以通过在link
字段中添加mssql
的配置,也可以增加独立的type
字段配置数据库类型。以下两种方式都是可以的:或者
冰紫
sqlserver 怎么执行存储过程,可以给个案例吗
冰紫
已经搞定了,不知道有没有其他写法
lshfong
配置里能设置默认排序吗,不然每次都要单独去手写一次排序。
dao.Xxx.OrderDesc("id")
AmarsDing
请教一下 强哥!!!!
postgres 数据库:
连接 : link.links = fmt.Sprintf("pgsql:user=%s password=%s host=%s port=%s dbname=postgres sslmode=disable", l.Username, l.Password, l.HostAddr, l.Port)
sslmode 如果不配置是不是默认开启,配置项是否为sslmode=disable?
如上link => db_master.GetAll("SELECT datname FROM pg_database")
访问其他计算机, 提示: pq: ��ɫ "Administrator" ������, SELECT DATNAME FROM PG_DATABASE
如果不加sslmode=disable ,提示:pq: SSL is not enabled on the server, SELECT DATNAME FROM PG_DATABASE
xushushun
你好 请教一下这个连接池最大闲置链接数是做什么用的。
Mr曹
郭强 v2.0.0-rc2 版本无法自动加载pgsql, issues : https://github.com/gogf/gf/issues/1585
---
closed
kobe
郭强
全自动的,程序不需要特殊调用,具体请参考:ORM链式操作-主从切换
jiftle
支持数据库密码加密吗,安全测试人员要求对数据库密码不能明文存储
郭强
可以通过
HOOK
实现,该功能将在下个版本发布。jiftle
好的,目前临时采用
g.Cfg().Get()
取到link
内容然后解密pwd
,再调用gdb.SetConfig()
设置数据库密码。请问
link
的解析代码在哪里看到,gf
代码看到头大也没有找到,希望能够讲解下大概的实现思路。鄙人实现的太丑陋了。
郭强
没这么复杂。根据你的业务场景,那你完全不需要使用
link
配置项,而是使用pass
字段,参考以下代码解析即可。jiftle
这样挺简洁的 good
Wilson liu
hi 郭强
升级到v2 database 的driver是mssql
出现这个错误
../../go/pkg/mod/github.com/gogf/gf/contrib/drivers/mssql/v2@v2.0.0-20220319145450-d1f76f3834e1/mssql.go:226:18: d.DoSelect undefined (type *Driver has no field or method DoSelect)
../../go/pkg/mod/github.com/gogf/gf/contrib/drivers/mssql/v2@v2.0.0-20220319145450-d1f76f3834e1/mssql.go:292:20: d.DoSelect undefined (type *Driver has no field or method DoSelect)
go.mod
Wilson liu
回一下状况:
应该版本差异造成的. 目前看到git hub 上也有类似的issue.
目前 建议使用以下版本.目前可以过了. 留下记录
require ( github.com/gogf/gf/contrib/drivers/mssql/v2 v2.0.0-20220314113956-2eec1bc61acf )
ljs
使用两个数据库,偶尔会报这个错误
connectex: Only one usage of each socket address (protocol/network address/port) is normally permitted., SELECT * FROM ...
下面是数据库配置
database:
logger:
path: "logs/sql"
level: "all"
stdout: false
ctxKeys: ["RequestId"]
default:
type: "mysql"
host: "127.0.0.1"
port: "3306"
user: "root"
pass: "root"
name: "axea"
prefix: "a_"
role: "master"
debug: true
MaxIdleConnCount: 5
MaxOpenConnCount: 20
MaxConnLifetime: 30
mall:
type: "mysql"
host: "127.0.0.1"
port: "3306"
user: "root"
pass: "root"
name: "b_axea"
prefix: "a_"
role: "master"
debug: true
MaxIdleConnCount: 5
MaxOpenConnCount: 20
MaxConnLifetime: 30
郭强
你提个issue,把报错的堆栈贴上。
为为三点
什么时候会考虑增加一个Scope属性,可能某个查询值会根据权限来决定where条件,如果都用where去判断感觉重复逻辑有点多。写个函数返回 *gdb.Model 感觉又不好看
郭强
请提
issue
记录,详细描述。糖水不加糖
ORM链式操作-Handler特性
为为三点
谢谢,之前用laravel和gorm都叫scope,这里叫handle一下子没找到
糖水不加糖
其实我也觉着挺奇怪的.其它语言框架成熟的ORM方法名抄一遍感觉更能快速上手.
LZC
[[database.mssql2008]]
link = "mssql:user id=sa;password=11122;server=192.168.10.19;port=1888;database=MES_KanbanPj;encrypt=disable"
[[database.mssql2000]]
link = "mssql:user id=sa;password=11122;server=192.168.10.1;port=1433;database=MES;encrypt=disable"
mssql2000版本的数据库无法正确连接,Invalid TDS stream: unknown token type returned: token(0), SELECT * FROM 班组人员清单 WHERE 姓名='李式'
wilson
升级到2.1之后数据库使用这种方式:
糖水不加糖
2.1后需要手动引入driver库
zhengjianyang
大哥这里的说明没写清楚吧、还是我理解错了
sqlite配置 sqlite: 文件绝对路径
(如:/var/lib/db.sqlite3
)lskj
oracle对应的Link,似乎现在不是oracle: 账号/密码@地址:端口/数据库名称
默认的应该是oracle: //账号:密码@地址:端口/数据库名称
驱动中的代码如下:
苏杰
设置timezone: "local" 会出错。
sql.Open failed for driver "mysql" by source "root:12345@tcp(127.0.0.1:3306)/test?charset=utf8&loc=local": unknown time zone local
不设置连接时区,导致预想存储的数据和数据库数据相差一天。应该是timezone: "Local"
王怡轩
gf自带的orm怎么实现多租户,分库?
王哈哈
2.1.3 集成clickhouse 执行 sql 会报错 Error: code: 115, message: Unknown setting charset
王哈哈
这是 orm 的bug 嘛?