【问题标题】:SELECT FOR UPDATE issue in Spring JDBC appSpring JDBC 应用程序中的 SELECT FOR UPDATE 问题
【发布时间】:2020-05-12 02:18:05
【问题描述】:

我正在使用SELECT ... FOR UPDATE 语句在我的 SpringBoot 应用程序中实现行级锁定。数据库:MySQL 5.7.28,连接器 - MariaDb java 客户端 2.5.2,连接池 HikariCP 2.7.9,spring boot 版本 - 2.0.3 Release。

持久性是由 Spring JDBC Template 完成的,而不是由 JPA 完成的。我正在使用基于注释的 Spring Transaction 管理,方法是在我的 DAO 方法上添加 @Transactional 注释。事务代理是通过 AspectJ 编译时编织 (@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)) 生成的。我确信事务管理器配置正确。

我编写了几个集成测试来验证当多个线程竞争更新同一行时出现竞争条件的可能性,该行应该被SELECT ... FOR UPDATE 锁定。

现在,测试在 95% 的情况下都有效,但是,当执行特定的 IT 序列时,有一个测试会失败。

我确信当测试失败时,不会强加行锁。

我已在服务器上启用 MySql 查询日志以帮助进行故障排除。

这是我在第一个线程执行SELECT ... FOR UPDATE 语句时看到的:

2020-01-26T12:54:06.681319Z  1219 Query set autocommit=0
2020-01-26T12:54:36.616097Z  1209 Query SELECT _listed_fields_ FROM _my_table_ WHERE id IN ('19qix6lvsfx') FOR UPDATE

似乎在错误的连接对象上设置了自动提交。我读对了吗? 12191209 这些数字是多少?

当一切正常时,日志如下所示:

2020-01-26T13:24:22.940787Z  1243 Query set autocommit=0
2020-01-26T13:24:36.515016Z  1243 Query SELECT _listed_fields_ FROM _my_table_ WHERE id IN ('19xbs7vv53r') FOR UPDATE

任何帮助将不胜感激。

【问题讨论】:

    标签: mysql spring-boot mariadb spring-jdbc spring-transactions


    【解决方案1】:

    我不喜欢autocommit=0,因为我最终可能会忘记COMMIT

    SELECT ... FOR UPDATE 仅在您处于事务中时适用(autocommit=0 表示您始终处于事务中)。

    您的一般日志的 sn-p 意味着所有连接都在设置该值,也许是重复的。不,每个连接都不受其他连接设置的影响。

    您在日志中看到任何 COMMIT 吗?你曾经发出 ROLLBACK 吗?

    【讨论】:

    • 遇到@Transactional注解时,spring jdbc会发出autocommit=0查询。它将事务切换到“手动”模式。我确实看到了提交并且没有回滚。我想我更好地理解了这个问题,在我的集成测试中,由于某种原因,框架正在多次创建 Datasource 的 bean,这需要创建几个 hikari 连接池。单独的集成测试完成后,这些连接池不会关闭。所以,我看到从错误的连接池借来的连接。这就是自动提交没有任何影响的原因。
    猜你喜欢
    • 2011-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 2011-06-28
    • 2011-06-08
    • 2014-11-29
    • 1970-01-01
    相关资源
    最近更新 更多