gpt4 book ai didi

mysql - 为什么mysql在两个事务同时更新时不以可重复读模式锁定一行?

转载 作者:行者123 更新时间:2023-11-29 06:34:50 24 4
gpt4 key购买 nike

我不知道我是否忘记设置一些属性来启用它。
我有两个事务将更改同一个表中的同一行。

  val f1 = Future {
mysqlDB.withTransaction {
implicit session =>
println("one===========query begin")
val name = Tables.User.filter(_.id === 2).map(_.name).run
println("one=========="+name)
Thread.sleep(3000)
println("one update change to x-f1")
Tables.User.filter(_.id === 2).map(_.name).update(name + "-f1")
println(Tables.User.filter(_.id === 2).run)
println("one============query end")
}
}

val f2 = Future {
mysqlDB.withTransaction {
implicit session =>
println("two===========query begin")
val name = Tables.User.filter(_.id === 2).map(_.name).run
println("two==========="+name)
Thread.sleep(2800)
println("two update change to x-f2")
Tables.User.filter(_.id === 2).map(_.name).update(name + "-f2")
println(Tables.User.filter(_.id === 2).run)
println("two============query end")
}
}

Await.result(f1, 10.seconds)
Await.result(f2, 10.seconds)

我使用上面相同的代码测试了 postgresql 和 mysql(它们都处于可重复模式)。我认为“一个”事务将失败,因为并发更新。

其实postgresql是有的,但是mysql运行无一异常(exception),“一”事务覆盖了“二”事务的结果。这意味着结果丢失了,很烦人。

    Run starting. Expected test count is: 2
JDBCTestSpec2:
transcation
two===========query begin
one===========query begin
one============Vector(ccc)
two==========Vector(ccc)
two update change to x-f2
Vector(UserRow(2,Vector(ccc)-f2))
two============query end
one update change to x-f1
- should lock a row(postgresql) *** FAILED ***
org.postgresql.util.PSQLException: 错误: 由于同步更新而无法串行访问
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2161)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1890)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:560)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:363)
at scala.slick.driver.JdbcInvokerComponent$UpdateInvoker$$anonfun$update$1.apply(JdbcInvokerComponent.scala:88)
at scala.slick.driver.JdbcInvokerComponent$UpdateInvoker$$anonfun$update$1.apply(JdbcInvokerComponent.scala:84)
at scala.slick.jdbc.JdbcBackend$SessionDef$class.withPreparedStatement(JdbcBackend.scala:191)
at scala.slick.jdbc.JdbcBackend$BaseSession.withPreparedStatement(JdbcBackend.scala:389)
...
transcation
two===========query begin
one===========query begin
two===========Vector(ccc)
one==========Vector(ccc)
two update change to x-f2
Vector(UserRow(2,Vector(ccc)-f2))
two============query end
one update change to x-f1
Vector(UserRow(2,Vector(ccc)-f1))
one============query end

有没有人可以帮助我?

问题已解决。我已经使用FOR UPDATE将一些代码发布到github:
https://gist.github.com/fairjm/99ce55160d4a4adf350b

最佳答案

@jilen 表必须使用 InnoDB 存储引擎来支持 MySQL 中的事务。将表转换为 InnoDB 表运行语句:

ALTER TABLE table_name ENGINE = InnoDB;

注意:

如果您需要锁定选定的记录,您必须使用SELECT ... FOR UPDATE ( mysql syntax ; postgresql syntax )。它is not supported natively in Slick但有一个解决方法:https://gist.github.com/cvogt/d9049c63fc395654c4b4

引用资料:

  1. Transaction and Atomic Operation Differences
  2. ALTER TABLE Syntax
  3. Feature Request: Support for "SELECT ... FOR UPDATE"

关于mysql - 为什么mysql在两个事务同时更新时不以可重复读模式锁定一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25589665/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com