我正在尝试复制某些记录并对其进行一些更改(至少是PK)。鉴于记录的数量可以变化,我决定采用流式方法来获取数据,并采用标准的Slick方法来持久化数据。
这是一个摘要:
val query = for {...} yield{...}
val stream = db.stream(query.result.withStatementParameters(rsType = ResultSetType.ForwardOnly, rsConcurrency = ResultSetConcurrency.ReadOnly, fetchSize = 20).transactionally)
这是流程定义:
val yourFlow = Flow[BigItem].mapAsync[String](1)(mapper)
var count = 0
val sink = Sink.foreach[String] { message =>
count = count + 1
Logger.info(message + " " + count)
}
val src = Source.fromPublisher(a)
val flow = src.via(yourFlow).to(sink)
flow.run()
这里定义了接收器,它只是用来验证流是否正常工作以及期望的元素数量是否通过。
有一个映射器:
val mapper: BigItem => Future[String] = (i: BigItem) => {...}
同样,这里没有什么令人印象深刻的东西,在一个映射器中,我修改了一个对象,创建了DBIO,然后存储了它。
db.run(itemRepository.makePersistentDBIO(bigItem)).map(_ => "OK")
这时,代码刚刚挂起。如果我使用一个简单的DBIO,而不使用DB做任何事情,或者尝试访问其他数据库表,那么一切都会顺利进行,并且整个流都将被加载,但是当我尝试将记录插入表中时,流正在获取数据不会插入任何记录。 我尝试使用事务隔离,游标配置,平滑配置,但无济于事。 所有数据库连接均处于空闲状态,一切都停止了。
有趣的是,一旦这件事挂起,通过psql客户端手动插入数据的工作就如预期的那样,这使我相信这与Postgres级别上的死锁无关,因为select应该不会阻塞,所以无论如何也没有太大意义其他交易。