微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用光滑的顺序操作和数据库状态;乱序行为

如何解决使用光滑的顺序操作和数据库状态;乱序行为

给定许多通过测试并且似乎可靠的方法,访问和更新独立递增的列(每条记录递增,因此它不是自动递增的列)。例如:

  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 举报,一经查实,本站将立刻删除。