gogf / gf

GoFrame is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
https://goframe.org
MIT License
11.47k stars 1.57k forks source link

g.DB().GetCache()无法获取表结构缓存,导致无法清空缓存 #1072

Closed 35598253 closed 1 year ago

35598253 commented 3 years ago

go:1.15.5

gf:1.14.6

手动在数据库表test中添加user字段 或 用g.DB().Exec()执行往数据表test中添加user字段

没有用model 模型直接 g.DB().Table('test').Insert(g.map{"user":1}) 提交时候,提示 no column of name user found for test 错误

重启服务,则正常运行;

群里讨论是数据表结构缓存原因, 而g.DB().GetCache() 无法获取缓存信息,导致无法清除缓存;

分析gf源码时在 gdb 运行调用 TableFields 生成表结构缓存(不是数据缓存),键值是fmt.Sprintf(mysql_tablefields%s_%s@group:%s, table, checkSchema, d.GetGroup()),

目前应急方案 在 gf/database/gdb/gdb_core.go 文件中添加

func (c *Core) Rmcache(table string) error{
    if _,err :=internalCache.Remove(fmt.Sprintf(`mysql_table_fields_%s_@group:%s`, table, c.GetGroup()));err != nil {
        return err
    } 
    return nil
}

想要刷新表缓存时,直接调用 g.DB().Table('test').Rmcache(table)即可,但总感觉像山寨的。。

gqcn commented 3 years ago

@35598253 看了下,内部确实是两个缓存对象,你这个处理还稍微需要花点时间。

35598253 commented 2 years ago

@gqcn 这个清除缓存的功能,还处理吗?

Nathanielna commented 2 years ago

@35598253 同样的问题,不过我是SQLSEVER,按你这办法也没执行重新查询

35598253 commented 2 years ago

@35598253 同样的问题,不过我是SQLSEVER,按你这办法也没执行重新查询

新版本的修改位置变更了,如果你需要我发给你!

Nathanielna commented 2 years ago

@35598253 目前我改成拼SQL语句原生执行了,如果你能告诉我改哪里是最好的了。 因为用SQL语句执行有很多弊端,比如这个字段数据库不存在就报错了

Nathanielna commented 2 years ago

@35598253 目前我改成拼SQL语句原生执行了,如果你能告诉我改哪里是最好的了。因为用SQL语句执行有很多弊端,比如这个字段数据库不存在就报错了

35598253 commented 2 years ago

Gdb.go 中添加 Recache(table string) error

对应的数据库驱动添加如下代码( 例子中是 Oracle的)

func (d *DriverOracle) Recache(table string) error {
    charL, charR := d.GetChars()
    table = gstr.Trim(table, charL+charR)
    if gstr.Contains(table, " ") {
        return gerror.NewCode(gcode.CodeInvalidParameter, "function TableFields supports only single table operations")
    }
    useSchema := d.schema.Val()

    tableFieldsCacheKey := fmt.Sprintf(
        `oracle_table_fields_%s_%s@group:%s`,
        table, useSchema, d.GetGroup(),
    )

    r := tableFieldsMap.Remove(tableFieldsCacheKey)
    if r == nil {
        return gerror.NewCode(gcode.CodeInvalidParameter, "Recache Table Is Not Find")
    }
    return nil
}

最终调用g.DB().Table('test').Recache(table) 即可

Nathanielna commented 2 years ago

@35598253 我看了下一共有5个gdb_driver_mssql、gdb_driver_mysql、gdb_driver_oracle、gdb_driver_pgsql、gdb_driver_sqlite 我改了mssql的那个,后面的4个都报错。不知道为啥,只要改了这5个文件,这个项目就会运行报错 . image

Nathanielna commented 2 years ago

C:\Users\yansir\go\pkg\mod\github.com\gogf\gf@v1.16.5\database\gdb\gdb_driver_mssql.go,这是文件路径,是不是改这里的 @35598253

Nathanielna commented 2 years ago

@35598253 可以了,感谢大哥。把其它没用的数据库全部注释就可以了。到时候写个按钮控制下需要的时候更新,不需要的时候就不触发了,每次触发感觉也挺吃时间的

35598253 commented 2 years ago

@Nathanielna 才看到,暴露函数其他驱动文件都的修改或注释,忘记和你说了,其实这个没必要每次都清除,我只有在动态增减table的时候才触发。。