为了账号安全,请及时绑定邮箱和手机立即绑定

使用 SQLC 时,如何使数据库连接在运行时可切换

使用 SQLC 时,如何使数据库连接在运行时可切换

Go
拉风的咖菲猫 2022-09-19 14:44:16
我知道这个问题已经被问过很多次了,但我没有为我的情况找到一个好的答案。我正在使用 SQLC 生成用于查询数据库的方法。使用开始时初始化的一个连接时,一切正常。现在,我需要在多租户环境中进行设置,其中每个租户将具有单独的数据库。现在,我想从连接映射(映射[字符串]*sql。DB) 将租户与数据库连接连接起来。我的问题是关于在运行时覆盖/选择连接。使用一个连接,存储库被初始化为:type Repository interface {    GetCustomerById(ctx context.Context, id int64) (Customer, error)    ListCustomers(ctx context.Context) ([]Customer, error)}type repoSvc struct {    *Queries    db *sql.DB}func NewRepository(dbconn *sql.DB) Repository {    return &repoSvc{        Queries: New(dbconn),        db:      dbconn,    }}customerRepo := customerRepo.NewRepository(conn)GetCustomerById 是 SQLC 生成的方法,连接是数据库连接如何根据参数(从 Cookie 或上下文)建立连接?
查看完整描述

1 回答

?
冉冉说

TA贡献1877条经验 获得超1个赞

假设您使用的是单独的数据库,最简单的方法是维护 ,其中是区分租户(例如,包含租户 ID 的 或)的方式。map[tenantID]RepositorytenantIDstringuint

这样,您就可以在运行时执行所有操作:

  • 当您需要添加租户时,只需实例化该租户并将其添加到地图中Repository

  • 当您需要删除租户时,只需将其从映射中删除并关闭数据库连接Repository

  • 当您需要对租户执行查询时,请在映射中查找相应的,并使用它来执行该租户的查询Repository

如果上述操作可能同时发生,请确保使用某种同步机制来避免访问映射时的数据争用(例如 、或 )。sync.Mapsync.RWMutex

如果您有一个存储租户及其数据库连接 URI 的数据库表,您仍然可以使用此方法:当您需要执行查询检查时,如果 缺少 :,则查询租户表并将该租户的 添加到映射中。然后,您可以定期扫描 并删除任何一段时间未使用的内容。RepositorymapRepositorymapRepository

为了使所有这些更容易,您还可以将整个机器包装到一个接口中,该接口与接口相同,但每个方法上都接受一个附加参数:MultitenantRepositoryRepositorytenantID

type MultitenantRepository interface {
    GetCustomerById(ctx context.Context, tenant tenantID, id int64) (Customer, error)
    ListCustomers(ctx context.Context, tenant tenantID) ([]Customer, error)
}

这将避免将多租户设置的所有复杂性暴露给业务逻辑。


查看完整回答
反对 回复 2022-09-19
  • 1 回答
  • 0 关注
  • 61 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信