如何解决使用光滑的顺序操作和数据库状态;乱序行为
给定许多通过测试并且似乎可靠的方法,访问和更新独立递增的列(每条记录递增,因此它不是自动递增的列)。例如:
def getVersion(id:Int): Future[Int] = db.run(query.filter(_.id === id).map(o => o.version).result.head)
def getAndIncrementVersion(id: Int): Future[Try[Int]] = {
val incrementAction = sql"""UPDATE TABLE SET VERSION = VERSION + 1 WHERE ID = ${id}""".as[Int]
val getVersionAction = query.filter(_.id === id).map(o => o.version).result.headOption
val dbAction = incrementAction.andThen(getVersionAction)
db.run(dbAction).map {
case Some(i) => Success(i)
case None => Failure[Int](new Exception("Error incrementing org counter"))
}
}
现在,如果我按顺序调用这些方法,即使我按顺序解析每个future,有时也会得到乱序的结果,例如
for {
i <- getVersion(1)
j <- getAndIncrementVersion(1)
k <- getVersion(1)
} yield (i,j,k)
哪个应该产生,例如(71,Success(72),72) 有时会产生 (71,72,71)。任何人都知道为什么会发生这种情况?
更多信息:
- 如果我在重复循环中运行它,它似乎只发生在第一遍。
- 如果我从
sbt test
运行它,它通常会通过。如果我在 sbt 中并反复调用test
它可能会在 3 或 4 次后失败。存在现有池尚未释放的警告。
提前致谢。
解决方法
您的数据库可能无法保证更改(来自更新)何时可见(对 getVersion
)。当您将每个部分作为独立查询运行时,您可能会得到不同的结果。如果您需要更严格的行为,我建议您将这些操作合并为一个操作并在事务中运行。
例如(并为错别字道歉——我没有尝试编译这个):
val action: DBIO[(Int,Int,Int)] = (for {
i <- getVersionAction
j <- incrementAction
k <- getVersionAction
} yield (i,j,k)).transactionally
我希望这能给您一致的结果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。