mysql - Slick 中的线程安全

标签 mysql scala asynchronous slick slick-3.0

我有一个关于 Slick/数据库如何管理异步操作的一般理解问题。当我编写查询或操作时,说

(for {
  users <- UserDAO.findUsersAction(usersInput.map(_.email))
  addToInventoriesResult <- insertOrUpdate(inventoryInput, user)  
  deleteInventoryToUsersResult <- inventoresToUsers.filter(_.inventoryUuid === inventoryInput.uuid).delete if addToInventoriesResult == 1
  addToInventoryToUsersResult <- inventoresToUsers ++= users.map(u => DBInventoryToUser(inventoryInput.uuid, u.uuid)) if addToInventoriesResult == 1 
} yield(addToInventoriesResult)).transactionally

是否有可能另一个用户可以在执行第一个操作 UserDAO.findUsersAction(usersInput.map(_.email)) 之后,但在其余操作之前删除用户,例如插入会失败(因为外键错误)?或者可能导致更新丢失的场景,例如:事务 A 读取数据,然后事务 B 更新此数据,然后事务 A 根据它读取的内容进行更新,它将看不到 B 的更新并覆盖它

我认为这可能取决于数据库实现或 JDBC,因为这是作为 SQL block 发送到数据库的,但也许 Slick 在其中发挥了作用。我正在使用 MySQL。

如果此处存在同步问题,解决此问题的最佳方法是什么?。我已经阅读了有关按顺序处理操作(作为语义单元)的后台队列之类的方法,但这不会部分消除能够异步访问数据库的好处 -> 性能不佳吗?

最佳答案

首先,如果底层数据库驱动程序是阻塞的(基于 JDBC 的驱动程序的情况),那么 Slick 无法提供真正非阻塞意义上的异步性能(即线程将被消耗和阻塞多长时间)给定的查询需要完成)。

有人在谈论为 Oracle 和 SQL Server(在付费的 Typesafe 订阅下)实现非阻塞驱动程序,但这不会很快发生 AFAICT。有一个couple of projects确实为 Postegres 和 MySQL 提供了非阻塞驱动程序,但 YMMV 仍处于早期阶段。

除此之外,当您调用 transactionally 时,Slick 会执行一批查询并将它们包装在带有底层连接的 autocommit 标志的 try-catch block 中设置为假。查询成功执行后,通过将 autocommit 设置回默认值 true 来提交事务。如果抛出异常,则调用连接的 rollback 方法。只是 Slick 方便地抽象出来的标准 JDBC session 样板。

至于用户在交易中被删除并正确处理的场景,这是底层数据库/驱动程序的工作。

关于mysql - Slick 中的线程安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34318194/

相关文章:

mysql - CONCAT() inside GROUP_CONCAT() with count

mysql - 图数据库,高效建模三节点组合关系

scala - 访问 scala future 返回的值

c# - 为什么 TaskFactory.FromAsync() 重载需要提供状态对象?

javascript - 异步 Javascript 递归

c# - 为什么 System.Net.Sockets.Socket.AcceptAsync 在长时间不活动后完成 ConnectionReset?

mysql - SQL 仅选择列上具有最大值的行

java - Android Room - 处理对象中的对象列表和查询结果

用于递归 bnf 的 Scala Parser Combinators 技巧?

scala - 如何在Scala中对整数元组列表进行排序