配置文件

我们推荐使用配置组件来管理数据库配置,并使用g对象管理模块中的g.DB("数据库分组名称")方法获取数据库操作对象,数据库对象将会自动读取配置组件中的相应配置项,并自动初始化该数据库操作的单例对象。数据库配置管理功能使用的是配置管理组件实现(配置组件采用接口化设计默认使用文件系统实现),同样支持多种数据格式如:toml/yaml/json/xml/ini/properties。默认并且推荐的配置文件数据格式为yaml

简单配置

v2.2.0版本开始,使用link进行数据库配置时,数据库组件统一了不同数据库类型的配置格式,以简化配置管理。

简化配置通过配置项link指定,格式如下:

type:username:password@protocol(address)[/dbname][?param1=value1&...&paramN=valueN]

即:

类型:账号:密码@协议(地址)/数据库名称?特性配置

其中:

  • 数据库名称 特性配置为非必须参数,其他参数为必须参数。
  • 协议可选配置为:tcp/udp/file,常见配置为tcp
  • 特性配置根据不同的数据库类型,由其底层实现的第三方驱动定义,具体需要参考第三方驱动官网。例如,针对mysql驱动而言,使用的第三方驱动为:https://github.com/go-sql-driver/mysql 支持的特性配置如multiStatementsloc等。

示例:

database:
  default:
    link:  "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
  user:
    link:  "sqlite::@file(/var/data/db.sqlite3)"

不同数据类型对应的link示例如下:

类型link示例extra参数
mysqlmysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=truemysql
mariadbmariadb:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=truemysql
tidbtidb:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=truemysql
pgsqlpgsql:root:12345678@tcp(127.0.0.1:5432)/testpq
mssql

mssql:root:12345678@tcp(127.0.0.1:1433)/test?encrypt=disable

go-mssqldb
sqlitesqlite::@file(/var/data/db.sqlite3)  (可以使用相对路径,如: db.sqlite3)go-sqlite3
oracleoracle:root:12345678@tcp(127.0.0.1:5432)/testgo-oci8
clickhouseclickhouse:root:12345678@tcp(127.0.0.1:9000)/test

clickhouse-go

dmdm:root:12345678@tcp(127.0.0.1:5236)/test

dm

框架支持的数据库类型请参考:https://github.com/gogf/gf/tree/master/contrib/drivers

完整配置

完整的config.yaml数据库配置项的数据格式形如下:

database:
  分组名称:
    host:                  "地址"
    port:                  "端口"
    user:                  "账号"
    pass:                  "密码"
    name:                  "数据库名称"
    type:                  "数据库类型(如:mariadb/tidb/mysql/pgsql/mssql/sqlite/oracle/clickhouse/dm)"
    link:                  "(可选)自定义数据库链接信息,当该字段被设置值时,以上链接字段(Host,Port,User,Pass,Name)将失效,但是type必须有值"         
    extra:                 "(可选)不同数据库的额外特性配置,由底层数据库driver定义"
    role:                  "(可选)数据库主从角色(master/slave),不使用应用层的主从机制请均设置为master"
    debug:                 "(可选)开启调试模式"
    prefix:                "(可选)表名前缀"
    dryRun:                "(可选)ORM空跑(只读不写)"
    charset:               "(可选)数据库编码(如: utf8/gbk/gb2312),一般设置为utf8"
	protocol:              "(可选)数据库连接协议,默认为TCP"
    weight:                "(可选)负载均衡权重,用于负载均衡控制,不使用应用层的负载均衡机制请置空"
    timezone:              "(可选)时区配置,例如:local"
    namespace:             "(可选)用以支持个别数据库服务Catalog&Schema区分的问题,原有的Schema代表数据库名称,而NameSpace代表个别数据库服务的Schema"
    maxIdle:               "(可选)连接池最大闲置的连接数"
    maxOpen:               "(可选)连接池最大打开的连接数"
    maxLifetime:           "(可选)连接对象可重复使用的时间长度"
	queryTimeout:          "(可选)查询语句超时时长"
	execTimeout:           "(可选)写入语句超时时长"
	tranTimeout:           "(可选)事务处理超时时长"
	prepareTimeout:        "(可选)预准备SQL语句执行超时时长"
    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"
    extra:         "local=Local&parseTime=true"
    role:          "master"
    debug:         "true"
    dryrun:        0
    weight:        "100"
    prefix:        "gf_"
    charset:       "utf8"
    timezone:      "local"
    maxIdle:       "10"
    maxOpen:       "100"
    maxLifetime:   "30s"
 	protocol

使用该配置方式时,为保证数据库安全,默认底层不支持多行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"

以上数据库配置示例中包含两个数据库分组defaultuser,其中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配置分组。

配置管理特点:

  1. 支持多节点数据库集群管理;
  2. 每个节点可以单独配置连接属性;
  3. 采用单例模式管理数据库实例化对象;
  4. 支持对数据库集群分组管理,按照分组名称获取实例化的数据库操作对象;
  5. 支持多种关系型数据库管理,可通过ConfigNode.Type属性进行配置;
  6. 支持Master-Slave读写分离,可通过ConfigNode.Role属性进行配置;
  7. 支持客户端的负载均衡管理,可通过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)将失效(该字段是一个扩展功能)
    Extra            string        // (可选)不同数据库的额外特性配置,由底层数据库driver定义
    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("数据库分组名称")来获取一个数据库操作对象。该对象用于后续的数据库一系列方法/链式操作。




Content Menu


  • No labels

22 Comments

  1. 在v2下使用sqlite时,使用该文档所述的link格式 (即sqlite::@file(文件名) ),结果一直报error14,打不开数据库。后面采用 sqlite: 文件名,则成功打开数据库。文档这里关于sqlite的使用是否存在问题?

    1. 这个格式是从v2.2版本开始支持,请使用最新版本框架。

  2. 配置中的updatedAt 自动更新的值是个字符串 “2022-10-14 13:46:09” 有没有指定用时间戳来替代该字符串时间的配置

    1. 郭强 这里时间戳自己转? 

  3. oraclemssql:root:12345678@tcp(127.0.0.1:5432)/testgo-oci8

    这个是错的吧,https://gfcdn.johng.cn 和  https://goframe.org/ 不同

  4. 使用pgsql的时候报:Error: missing "=" after "postgres:123456@tcp(localhost:5432)/dev_db" in connection info string"

    1. 仔细看下文档pgsql:root:12345678@tcp(127.0.0.1:5432)/test

      1. 我的数据库配置是这样的 

        "pgsql:postgres:123456@tcp(127.0.0.1:5432)/dev_db"
        实际报错:

        2022-10-22 09:17:13.082 {2caffb3e463f20178b74fb6d0d7a0bee} 200 "POST http 127.0.0.1:8000 /user/sign-up HTTP/1.1" 0.018, 127.0.0.1, "", "PostmanRuntime/7.29.2", 52, "Database Operation Error", ""
        Stack:
        1. missing "=" after "postgres:123456@tcp(127.0.0.1:5432)/dev_db" in connection info string", SELECT COUNT(1) FROM "user"

        1. 也要同时升级driver:go get -u github.com/gogf/gf/contrib/drivers/mysql/v2

          1. 感谢老哥,升级一下就没问题了

  5. 这个有类似gorm的migration功能吗,表还是要自己提前创建好吗,那修改表结构不是很麻烦

    1. 貌似没有,需要自己导SQL文件

  6. 连接clickhouse查询数据,请问这个错误和版本有关系嘛

    CLI Built Detail:
      Go Version:  go1.19.2
      GF Version:  v2.2.5
      Git Commit:  none
      Build Time:  2022-11-29 16:16:54

    clickhouse版本:22.2.2

    配置文件:

    # Database.
    database:
    logger:
    level: "all"
    stdout: true
    # 默认mysql数据源
    default:
    link: "mysql:root:123456@tcp(xxx.xxx.xxx.xxx:3306)/test"
    debug: true
    # clickhouse数据源
    ck:
    link: "clickhouse:default:123456@tcp(xxx.xxx.xxx.xxx:9000)/default"
    debug: true
    charset: utf8

    异常日志:

    [clickhouse][conn=1][XXX.XXX.XXX.XXX:9000][send query] compression=%!t(clickhouse.CompressionMethod=2) select * from 表名 where name= 'sss'
    [clickhouse][conn=1][XXX.XXX.XXX.XXX:9000][send data] compression=%!t(clickhouse.CompressionMethod=2)
    [clickhouse][conn=1][XXX.XXX.XXX.XXX:9000][exception] code: 115, message: Unknown setting charset
    2022-11-30 11:17:18.817 [ERRO] {285d7715763e2c1752303151bcfd403a} [ 80 ms] [ck] [default] [rows:0  ] select * from 表名 where name= 'sss'
    Error: code: 115, message: Unknown setting charset

  7. sqlite数据库在开发模式下可以使用相对路径,相对路径由项目路径开始

    下面配置将会读取文件的路径:项目文件夹/manifest/document/sqlite/focus.db 

    database:
        default:
            link: "sqlite::@file(manifest/document/sqlite/focus.db)"


  8. 有微信交流群吗? 求拉

    1. 这个页面有微信群的信息 框架介绍(v2.7.x)

  9. GoFrame CLI Tool v2.3.1  pgsql 遇到的一些问题(已解决


    cannot find database driver for specified database type "pgsql", did you misspell type name "pgsql" or forget importing the database driver?  possible reference: https://github.com/gogf/gf/tree/master/contrib/drivers

    遇到此问题 不需要下载CLI源码 添加驱动编译!!!



    go get -u github.com/gogf/gf/contrib/drivers/pgsql/v2

    并在 main.go 添加


    _ "github.com/gogf/gf/contrib/drivers/pgsql/v2"

    如果gen dao 生成代码报错 同样执行以上步骤 重新 gen dao


    其他数据库同理

    gf 默认支持的数据库 https://github.com/gogf/gf/tree/master/contrib/drivers


  10. pgsql有个关于表别名的BUG:

    代码:

    model := dao.BaseDept.Ctx(ctx).As("A")

    err = model.LeftJoin(dao.BaseOrg.Table(), "B", fmt.Sprintf("A.%s=B.%s",
    dao.BaseDept.Columns().COrgId, dao.BaseOrg.Columns().Id,
    )).Fields(fmt.Sprintf("A.*,B.%s AS c_org_name", dao.BaseOrg.Columns().CName)).Scan(&res)

    ----------------------------------------

    出错信息:

    SELECT A.*,B.c_name AS c_org_name FROM "tb_base_dept" AS A LEFT JOIN\"tb_base_org" AS "B" ON (A.c_org_id=B.id) WHERE "A"."deleted_at" IS NULL AND "B"."deleted_at" IS NULL: pq: 对于表\"b\",丢失FROM子句项

    --------------------------------------------

    原因分析:

    在生成的SQL语句中,发现两个表的别名A和B,有些有双引号,有些没有(当然其中也有我的代码中硬编码的也没有加双引号),

    如果将所有硬编码部分的A、B都写成"\"A\"" "\"B\""这样也是可以的,但显得非常麻烦,而且容易出错

    这个问题应该是仅出现在多表操作时,单表操作没有发现这个问题


  11. pgsql 我看是使用 lib/pq , lib/pq 已進入維護模式不再新增功能

    有考慮更換為 pgx 嗎?

    1. 可以提pr哈

  12. 提一个bug,达梦数据库link`dm:root:12345678@tcp(127.0.0.1:5236)/test`  这么写的的话会出现不指定达梦模式的问题,需要这样写才能指定连接模式 `dm:root:12345678@tcp(127.0.0.1:5236)/test?schema=test`

    1. 看起来似乎是配置的问题,如果觉得是BUG欢迎提PR参与共建。