跳到主要内容
版本:1.16.x

ORM 支持传递自定义的 context 上下文变量,用于异步 IO 控制、上下文信息传递(特别是链路跟踪信息的传递)、以及嵌套事务支持。

我们可以通过 Ctx 方法传递自定义的上下文变量给 ORM 对象, Ctx 方法其实是一个链式操作方法,该上下文传递进去后仅对当前 DB 接口对象有效,方法定义如下:

func Ctx(ctx context.Context) DB

示例1,请求超时控制

我们来看一个通过上下文变量控制请求超时时间的示例。

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
_, err := db.Ctx(ctx).Query("SELECT SLEEP(10)")
fmt.Println(err)

该示例中执行会 sleep 10 秒中,因此必定会引发请求的超时。执行后,输出结果为:

context deadline exceeded, SELECT SLEEP(10)

示例2,链路跟踪信息

上下文变量也可以传递链路跟踪信息,并且可以和日志组件结合,将链路信息打印到日志中(仅当 ORM 日志开启时)。

我们来看一个示例。

1、数据库配置示例:

[database]
[database.logger]
Path = "/tmp/log/gf-app/sql"
Level = "all"
Stdout = true
CtxKeys = ["Trace-Id"]
[database.default]
link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
debug = true

其中,我们通过日志组件的 CtxKeys 配置来指定需要打印到日志中的上下文信息中的变量名称,因此当 context 上下文变量中存在键名为 Trace-Id 的变量时,将会被自动打印到日志中。关于日志组件的上下文特性介绍具体请参考 日志组件-Context上下文 章节。同时,仅当数据库配置的 debug 打开时才会记录完整的 SQL 执行日志,因此这里配置中的 debug=true

ORM 组件同时支持 goframe 框架的 logger 组件 CtxKeys 特性(自定义链路信息传递),同时也支持标准的 OpenTelemetry 链路跟踪信息传递,具体请参考章节: 链路跟踪

2、 Golang 代码示例

package main

import (
"context"
"github.com/gogf/gf/frame/g"
)

func main() {
ctx := context.WithValue(context.Background(), "Trace-Id", "123456789")
_, err := g.DB().Ctx(ctx).Query("SELECT 1")
if err != nil {
panic(err)
}
}

为简化示例,我们这里手动构造了一个 ctx 变量,并存放了一个 Trace-Id 的键值对,键值为 123456789。执行后,终端输出为:

2020-12-28 23:43:03.055 [DEBU] {Trace-Id: 123456789} [  3 ms] [default] SELECT 1

示例3,模型上下文操作

模型对象也支持上下文变量的传递,同样也是通过 Ctx 方法。我们来看一个简单的示例,我们将示例2的例子通过模型操作调整一下。

package main

import (
"context"
"github.com/gogf/gf/frame/g"
)

func main() {
ctx := context.WithValue(context.Background(), "Trace-Id", "123456789")
_, err := g.DB().Model("user").Ctx(ctx).All()
if err != nil {
panic(err)
}
}

执行后,终端输出为:

2020-12-28 23:46:56.349 [DEBU] {Trace-Id: 123456789} [  5 ms] [default] SHOW FULL COLUMNS FROM `user`
2020-12-28 23:46:56.354 [DEBU] {Trace-Id: 123456789} [ 5 ms] [default] SELECT * FROM `user`

其中 SHOW FULL COLUMNS FROM `user` ORM 组件的数据表字段获取查询,每个表在执行操作之前仅会查询一次并缓存结果到内存中。

示例4,嵌套事务支持

嵌套事务的支持依赖 Context 上下文变量的层级传递,具体请参考章节: ORM事务处理