蒸气3:使用多个数据库

Agr*_*nsh 2 database vapor

使用Vapor 3,有没有一种简单的方法可以在服务器运行时切换数据库?

例如,用户使用“登录”数据库登录。然后,我在他们的Cookie中为该用户设置数据库。然后,来自该用户的任何后续请求都将使用cookie中标识的数据库(在这种情况下,“用户”实际上是一家公司)。

所有数据库都来自相同的数据库家族(例如MySQL)。这样可以将每个公司的数据保留在各自的数据库中,并限制每个数据库的大小(并且希望总体而言,数据库操作会更快)。此外,还原数据库的任何需求只会影响一家公司,并且备份会更简单。

  1. 如何实现呢?
  2. 这会非常低效吗?

还有其他更好的方法来实现这一目标吗?

imi*_*ike 6

据我了解,您可以创建一些不同的数据库标识符,例如:

extension DatabaseIdentifier {
    static var db1: DatabaseIdentifier<MySQLDatabase> {
        return .init("db1")
    }
    static var db2: DatabaseIdentifier< MySQLDatabase > {
        return .init("db2")
    }
}
Run Code Online (Sandbox Code Playgroud)

然后configure.swift像这样注册他们

let db1 = MySQLDatabase(config: MySQLDatabaseConfig(hostname: "localhost", username: "root", database: "db1"))
let db2 = MySQLDatabase(config: MySQLDatabaseConfig(hostname: "localhost", username: "root", database: "db2"))
var databaseConfig = DatabasesConfig()
databaseConfig.add(database: db1, as: .db1)
databaseConfig.add(database: db2, as: .db2)
services.register(databaseConfig)
Run Code Online (Sandbox Code Playgroud)

之后,别忘了在各处使用.db1.db2标识符,而不是默认值.mysql(对于MySQL),例如在迁移中

migrations.add(model: User.self, database: .db1)
Run Code Online (Sandbox Code Playgroud)

与池连接

return req.requestPooledConnection(to: . db1).flatMap { conn in
    defer { try? req.releasePooledConnection(conn, to: . db1) }
    return User.query(on: conn).all()
}
Run Code Online (Sandbox Code Playgroud)

和交易中

return req.transaction(on: .db1) { conn in
    return User.query(on: conn).all()
}
Run Code Online (Sandbox Code Playgroud)

对不起,如果我没有回答您的问题。我了解如果Fluent可以支持为每个查询传递数据库名称,那就太好了,但是我没有在其中找到它。(或者不清楚如何在查询中传递数据库名称)

但是顺便说一句,从我的角度来看,为每个客户端使用单独的数据库可能会让您对迁移感到头疼……也许最好将它们全部存储在一个数据库中但要进行分区?例如对于PostgreSQL,如此处所述