MySQL
在我的应用程序中,我必须与多个数据库一一交互(只读) 。对于每个数据库,我需要一定数量的连接。与数据库的交互不会一次性发生:我查询数据库,花一些时间处理结果,再次查询数据库,再次处理结果等等。
这些交互中的每一个都需要多个连接[我同时触发多个查询],因此我需要一个ConnectionPool
在我开始与数据库交互时产生并一直存在直到我完成对该数据库的所有查询(包括当我'不查询,只处理结果)。
我能够成功创建一个ConnectionPool
具有所需连接数并获得implicit session
如下所示的
def createConnectionPool(poolSize: Int): DBSession = {
implicit val session: AutoSession.type = AutoSession
ConnectionPool.singleton(
url = "myUrl",
user = "myUser",
password = "***",
settings = ConnectionPoolSettings(initialSize = poolSize)
)
session
}
implicit session
然后,我在需要与 DB 交互的所有方法中传递它。这样,我就可以使用 this同时poolSize
触发任何查询。很公平。session
def methodThatCallsAnotherMethod(implicit session: DBSession): Unit = {
...
methodThatInteractsWithDb
...
}
def methodThatInteractsWithDb(implicit session: DBSession): Unit = {
...
getResultsParallely(poolSize = 32, fetchSize = 2000000)
...
}
def getResultsParallely(poolSize: Int, fetchSize: Int)(implicit session: DBSession): Seq[ResultClass] = {
import java.util.concurrent.Executors
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
implicit val ec: ExecutionContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(poolSize))
val resultsSequenceFuture: Seq[Future[ResultClass]] = {
(0 until poolSize).map { i =>
val limit: Long = fetchSize
val offset: Long = i * fetchSize
Future(methodThatMakesSingleQuery(limit, offset))
}
}
val resultsFutureSequence: Future[Seq[ResultClass]] = Future.sequence(resultsSequenceFuture)
Await.result(resultsFuture, 2.minutes)
}
这种技术有两个问题:
- 我的应用程序很大并且有很多嵌套的方法调用,所以
implicit session
像这样通过所有方法(见下文)是不可行的。 - 除了上述与不同数据库的交互之外,我还需要在整个应用程序的整个生命周期中与另一个(固定)数据库建立单一连接。每隔几分钟,此连接将用于进行一次小型写入操作(记录我与其他 DB 交互的进度)。因此,我需要多个
ConnectionPool
s,每个 DB 一个
从我可以从ScalikeJdbc
's docs中获得的信息,我想出了以下不需要我通过implicit session
任何地方的方法。
def createConnectionPool(poolName: String, poolSize: Int): Unit = {
ConnectionPool.add(
name = poolName,
url = "myUrl",
user = "myUser",
password = "***",
settings = ConnectionPoolSettings(initialSize = poolSize)
)
}
def methodThatInteractsWithDb(poolName: String): Unit = {
...
(DB(ConnectionPool.get(poolName).borrow())).readOnly { implicit session: DBSession =>
// interact with DB
...
}
...
}
虽然这可行,但我不再能够并行化 db-interaction。这种行为很明显,因为我使用的是从poolborrow()
获取单个连接的方法。反过来,这让我想知道为什么这件事更早起作用:为什么我能够使用一个单一的同时触发多个查询?如果那件事奏效了,那为什么这不起作用呢?但是我没有找到如何从支持多个连接的 a 中获取 a 的示例。AutoSession
implicit session
DBSession
ConnectionPool
总而言之,我有 2 个问题和 2 个解决方案:每个问题一个。但我需要一个解决这两个问题的单一(通用)解决方案。
ScalikeJdbc
的有限文档没有提供很多帮助,并且ScalikeJdbc
几乎不存在有关的博客/文章。请提出正确的方法/一些解决方法。
框架版本
Scala 2.11.11
"org.scalikejdbc" %% "scalikejdbc" % "3.2.0"